java nio 网络编程

  • Post author:
  • Post category:java


java nio 网络编程

三要素

  • Channel:通道,想象成自来水管,所有的数据都要通道来传递
  • Buffer:缓冲区,负责从通道中读写数据,注意,读是从通道中读到缓冲,写是从缓冲写入通道
  • Selector:多路复用器,负责监视通道,如果通道的数据就绪,可以通过 Selector 获取 SelectionKey 进而得到就绪状态的 Channel 集合

打个比方

缓冲区就是水桶,通道是自来水管,多路复用器是保安。

这里有个保安,负责看守所有的水管,你要新建一个连接也就是要新加一个水管,那么你需要注册,也就是告诉保安。当然,你还要告诉保安,这根水管在什么情况下,你需要保安给你反馈。比如有人来接水了,有人来存水了,水龙头打开了等。

所以你知道了,我们的自来水管是双向的,可以接水,也可以存水。缓冲区也就是水桶,就是负责接水或者存水的装置。写数据就是将水桶的水往水管存,读数据就是将水管的水往水桶倒。

看张图:

这里写图片描述


从图中可以看出,服务器上所有Channel(包括ServerSocketChannel和SocketChannel)都需要向Selector注册,而该Selector则负责监视这些Socket的IO状态,当其中任意一个或者多个Channel具有可用的IO操作时,该Selector的select()方法将会返回大于0的整数,该整数值就表示该Selector上有多少个Channel具有可用的IO操作,并提供了selectedKeys()方法来返回这些Channel对应的SelectionKey集合。正是通过Selector,使得服务器端只需要不断地调用Selector实例的select()方法即可知道当前所有Channel是否有需要处理的IO操作。

类与方法

  • 创建多路复用器:

    Selector selector = Selector.open();
  • 创建服务端通道:

    ServerSocketChannel servChannel = ServerSocketChannel.open();
  • 通道设置为非阻塞:

    servChannel.configureBlocking(false);
  • 通道绑定端口:

    servChannel.socket().bind(new InetSocketAddress(port), 1024);
  • 通道注册到复用器,监听接收操作:

    servChannel.register(selector, SelectionKey.OP_ACCEPT);
  • 获取就绪状态 Channel,每秒轮询:

    int num = selector.select(1000);
  • 返回就绪状态的 Channel 的 SellectionKey 集合:

    Set<SelectionKey> selectedKeys = selector.selectedKeys();
  • 对就绪状态的 Channel 集合进行迭代,进行网络的异步读写操作

SelectionKey 的操作


  • isValid()

    是否可用

  • isAcceptable()

    新连接到来,然后获取 channel 转成 SocketServerChannel,再然后调用 accept 获取 SocketChannel,将 SocketChannel 注册到 Selector 上

  • isReadable()

    Channel 已就绪,直接读就可以了

  • isConnectable()

    通道是否已连接

  • channel()

    获取通道



版权声明:本文为m0_37659871原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。