非阻塞SOCKET

非阻塞的通信

ACCEPT:立即返回。如果没有client连接则返回null,有连接则返回SocketChannel(相当于阻塞网络通信里的Socket)

READ:立即返回

  • read():如果读不了则立即返回
  • read(ByteBuffer):尽量读,可能读几个甚至0个字节,也可能返回-1表示连接关闭

WRITE:立即返回 可能写入几个甚至0个字节

哪些是非阻塞

NIO之前的IO都是阻塞的,NIO里面也有阻塞、非阻塞之分

Channel子类

  • 阻塞NIO是继承于AbstractInterruptibleChannel,例如FileChannel

  • 非阻塞的NIO是继承于SelectableChannel,包括ServerSocketChannel, SocketChannel(TCP), DatagramChannel(UDP)

SelectableChannel子类

SelectableChannel

SelectableChannel

SelectableChannel通过configureBlocking(boolean) 来设置阻塞/非阻塞

非阻塞实现:SelectableChannel + Selector

Selector

非阻塞的IO实现了不用阻塞,但仍需人工不断去询问,因此需要一个用来轮询的东西帮忙管理,这就是Selecter,类似于OS层面的select/epoll

  • 存放的是SelectionKey
  • 构造:Select.open()

Selector

  • Selector类似一个观察者,只要我们把需要探知的套接字通道socketchannel注册到Selector,程序不用阻塞等待,可以并行做别的事情,当有事件发生时,Selector会通知程序,传回一组SelectionKey,程序读取这些Key,就会获得注册过的socketchannel,然后,从这个Channel中读取和处理数据

    • Selector内部原理实际是在做一个对所注册的channel的轮询访问,不断的轮询(目前就这一个算法),一旦轮询到一个channel有所注册的事情发生,比如数据来了,他就会站起来报告,交出一把钥匙,让我们通过这把钥匙来读取这个channel的内容。

SelectionKey

用于标注注册事件的信息,以Channel为单位,因为register()是Channel的方法

SelectionKey

Channel

  • Channel会发生事件:ACCEPT、READ、WRITE等
  • Channel通过register()方法在Selector上注册需要监控的事件 -register
    • 其中Object是Attach的一个对象,取出时用 Selectionkey.attachment(),并强制类型转换