设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 数据 手机
当前位置: 首页 > 服务器 > 系统 > 正文

Tomcat 中的 NIO 源码分析(10)

发布时间:2020-01-07 12:09 所属栏目:52 来源:站长网
导读://eitherwetimedoutorwewokeup,processeventsfirst //这里没什么好说的,顶多就再执行一次events方法 if(keyCount==0)hasEvents=(hasEvents|events); //如果刚刚select有返回readykeys,进行处理 IteratorSelection

//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 != ) { 

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读