Tomcat 中的 NIO 源码分析
//either we timed out or we woke up, process events first // 这里没什么好说的,顶多就再执行一次 events 方法 if ( keyCount == 0 ) hasEvents = (hasEvents | events);
// 如果刚刚 select 有返回 ready keys,进行处理 Iterator<SelectionKey> iterator = keyCount > 0 ? selector.selectedKeys.iterator : ; // Walk through the collection of ready keys and dispatch // any active event. while (iterator != && iterator.hasNext) { SelectionKey sk = iterator.next; NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment; // Attachment may be if another thread has called // cancelledKey if (attachment == ) { iterator.remove; } else { iterator.remove; // ※※※※※ 处理 ready key ※※※※※ processKey(sk, attachment); } }//while
//process timeouts timeout(keyCount,hasEvents); }//while
getStopLatch.countDown; } poller 的 run 方法主要做了调用 events 方法和处理注册到 Selector 上的 ready key,这里我们暂时不展开 processKey 方法,因为此方法必定是及其复杂的。 我们回过头来看之前从 acceptor 线程中调用的 register 方法。 Poller # register public void register(final NioChannel socket) { socket.setPoller(this); NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this); socket.setSocketWrapper(ka); ka.setPoller(this); ka.setReadTimeout(getConnectionTimeout); ka.setWriteTimeout(getConnectionTimeout); ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests); ka.setSecure(isSSLEnabled);
PollerEvent r = eventCache.pop; ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
// 注意第三个参数值 OP_REGISTER if ( r==) r = new PollerEvent(socket,ka,OP_REGISTER); else r.reset(socket,ka,OP_REGISTER);
// 添加 event 到 poller 中 addEvent(r); } 这里将这个 socket(包含 socket 和 buffer 的 NioChannel 实例) 包装为一个 PollerEvent,然后添加到 events 中,此时调用此方法的 acceptor 结束返回,去处理新的 accepted 连接了。 接下来,我们已经知道了,poller 线程在循环过程中会不断调用 events 方法,那么 PollerEvent 的 run 方法很快就会被执行,我们就来看看刚刚这个新的连接被注册到这个 poller 后,会发生什么。 PollerEvent # run @Override public voidrun { // 对于新来的连接,前面我们说过,interestOps == OP_REGISTER if (interestOps == OP_REGISTER) { try { // 这步很关键!!! // 将这个新连接 SocketChannel 注册到该 poller 的 Selector 中, // 设置监听 OP_READ 事件, // 将 socketWrapper 设置为 attachment 进行传递(这个对象可是什么鬼都有,往上看就知道了) socket.getIOChannel.register( socket.getPoller.getSelector, SelectionKey.OP_READ, socketWrapper); } catch (Exception x) { log.error(sm.getString("endpoint.nio.registerFail"), x); } } else { /* else 这块不介绍,省得大家头大 */
final SelectionKey key = socket.getIOChannel.keyFor(socket.getPoller.getSelector); try { if (key == ) { // The key was cancelled (e.g. due to socket closure) // and removed from the selector while it was being // processed. Count down the connections at this point // since it won't have been counted down when the socket // closed. socket.socketWrapper.getEndpoint.countDownConnection; } else { final NioSocketWrapper socketWrapper = (NioSocketWrapper) key.attachment; if (socketWrapper != ) { (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |