NIO各种事件
-
客户端的
SocketChannel
支持OP_CONNECT
,OP_READ
,OP_WRITE
三个操作。服务端ServerSocketChannel
只支持OP_ACCEPT
操作,在服务端由ServerSocketChannel
的accept()
方法产生的SocketChannel
只支持OP_READ
,OP_WRITE
操作。client/Server SocketChannel/ServerSocketChannel OP_ACCEPT OP_CONNECT OP_WRITE OP_READ client SocketChannel Y Y Y server ServerSocketChannel Y server SocketChannel Y Y -
就绪条件
OP_ACCEPT
就绪条件:当收到一个客户端的连接请求时,该操作就绪。这是ServerSocketChannel
上唯一有效的操作。OP_CONNECT
就绪条件:只有客户端SocketChannel
会注册该操作,当客户端调用SocketChannel.connect()
时,该操作会就绪。OP_READ
就绪条件:该操作对客户端和服务端的SocketChannel
都有效,当OS的读缓冲区中有数据可读时,该操作就绪。OP_WRITE
就绪条件:该操作对客户端和服务端的SocketChannel
都有效,当OS的写缓冲区中有空闲的空间时(大部分时候都有),该操作就绪。
OP_CONNECT
-
客户端调用
connect()
并注册OP_CONNECT
事件后,连接操作就会就绪,但是连接就绪不代表连接成功。OP_CONNECT
底层本质上是Write
SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); channel.connect(addr); channel.register(selector, SelectionKey.OP_CONNECT); //判断连接就绪,通过`finishConnect()`判断 if (key.isValid() && key.isConnectable()) { SocketChannel ch = (SocketChannel) key.channel(); if (ch.finishConnect()) { // Connect successfully // key.interestOps(SelectionKey.OP_READ); } else { // Connect failed } }
OP_ACCEPT
-
OP_ACCEPT
的处理与OP_CONNECT
基本一样,服务端监听,并注册OP_ACCEPT
事件后,就已准备好接受客户端的连接了ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.socket().bind(new InetSocketAddress(port)); channel.register(selector, SelectionKey.OP_ACCEPT); if (key.isValid() && key.isAcceptable()) { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel ch = ssc