NIO demo入门

本文通过实例介绍了NIO(非阻塞I/O)的基础应用,包括如何创建NIO服务器端(NIOServer)和客户端(NIOClient)。通过学习,读者将能够理解NIO在异步数据传输中的基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NIOServer:

package com.mp.thread

import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.{SelectionKey, Selector, ServerSocketChannel, SocketChannel}

object NioServer08 {
  def main(args: Array[String]): Unit = {
    val server = new NioServer08(8888)
    server.init
    server.run()
  }

}

class NioServer08(port:Int) extends Runnable{
  // 初始化多路复用器
  private var selector:Selector = _
  // 初始化读写缓存
  private var readBuffer:ByteBuffer = ByteBuffer.allocate(1024)
  private var writeByffer: ByteBuffer = ByteBuffer.allocate(1024)

  def init: Unit = {
    println("初始化服务器")
    selector = Selector.open()
    // 开启服务器通道
    val serverSocketChannel = ServerSocketChannel.open()
    serverSocketChannel.bind(new InetSocketAddress(port))
    // 设置非阻塞
    serverSocketChannel.configureBlocking(false)

    // 设置并标记服务状态
    serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT)

    println("服务器启动了....")
  }

  override def run(): Unit = {
    while (true) {
      // 阻塞方法,当至少有一个通道被选中,才能返回
      selector.select
      // 返回已选择的通道标记集合,集合中保存的是通道的标记,相当于通道的id
      val keys = selector.selectedKeys().iterator()
      while (keys.hasNext){
        val key = keys.next()
        // 移除处理过的key
        keys.remove()

        if(key.isAcceptable){
          acceptHandle(key)
        }else if (key.isReadable){
          readHandle(key)
        }else if (key.isWritable) {
          writeHandle(key)
        }
      }
    }
  }

  def acceptHandle(key: SelectionKey): Unit = {
    // 获取服务器通道
    val serverChannel = key.channel().asInstanceOf[ServerSocketChannel]

    // 阻塞方法,等待客户端连接
    val channel = serverChannel.accept()
    // 设置非阻塞
    channel.configureBlocking(false)
    println("有客户端连接进来了...")

    // 设置对应客户端的通道标记状态,此通道为读取数据使用
    channel.register(selector,SelectionKey.OP_READ)

  }

  def readHandle(key: SelectionKey): Unit = {
    // 获取通道
    val channel = key.channel().asInstanceOf[SocketChannel]

    // 设置非阻塞
    channel.configureBlocking(false)
    // 清空缓存
    this.readBuffer.clear()

    val len = channel.read(readBuffer)  // 阻塞方法,等待缓存中有数据
    if (len == -1 ){
      channel.close()
      key.cancel()
    }
    this.readBuffer.flip() // 重置buffer游标,避免数据的不一致

    val str = new String(readBuffer.array(),"UTF-8")
    println("从客户端接收数据:"+ str)
  }

  def writeHandle(key: SelectionKey): Unit = {

  }
}

NIO Client:

package com.mp.thread;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

/**
 * ClassName: NioClient07
 * Function:  TODO
 * Date:      2020-01-28 15:05
 * author     mapeng
 * version    V1.0
 */
public class NioClient07 {
    public static void main(String[] args) {
        try {
            SocketChannel channel = SocketChannel.open();
            // 连接远程服务器
            channel.connect(new InetSocketAddress(8888));
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            // 设置非阻塞
            channel.configureBlocking(false);
            while (true){
                System.out.println("请输入msg:");
                Scanner scanner = new Scanner(System.in);
                String line = scanner.nextLine();
// 将控制台数据写入到缓存
                buffer.put(line.getBytes("UTF-8"));
                buffer.flip();
                // 发送服务器
                channel.write(buffer);
                buffer.clear();

                /*int len = channel.read(buffer);
                if(len == -1){
                    break;
                }
                buffer.flip();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                System.out.println("接收客户端信息:" + new String(bytes,"UTF-8"));
                buffer.clear();*/


            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值