voiddoExecute()throwsIOException{while(!Thread.currentThread().isInterrupted()){//获取IO事件finalint readyCount =this.selector.select(this.selectTimeoutMillis);if(getStatus().compareTo(IOReactorStatus.SHUTTING_DOWN)>=0){if(this.shutdownInitiated.compareAndSet(false,true)){initiateSessionShutdown();}closePendingChannels();}if(getStatus()==IOReactorStatus.SHUT_DOWN){break;}// 处理 selected I/O events 1.client发起请求会触发该方法(可写)
2.response返回会触发该方法(可读)
if(readyCount >0){processEvents(this.selector.selectedKeys());}validateActiveChannels();// Process closed sessionsprocessClosedSessions();// If active process new channelsif(getStatus()==IOReactorStatus.ACTIVE){processPendingChannels();//处理请求,下边会有介绍processPendingConnectionRequests();}// Exit select loop if graceful shutdown has been completedif(getStatus()==IOReactorStatus.SHUTTING_DOWN&&this.selector.keys().isEmpty()){break;}if(getStatus()==IOReactorStatus.SHUT_DOWN){break;}}}
privatevoidprocessPendingConnectionRequests(){IOSessionRequest sessionRequest;//从requestQueue中获取待处理的请求for(int i =0; i <MAX_CHANNEL_REQUESTS&&(sessionRequest =this.requestQueue.poll())!=null; i++){if(!sessionRequest.isCancelled()){finalSocketChannel socketChannel;try{//创建channel也就是fd
socketChannel =SocketChannel.open();}catch(finalIOException ex){
sessionRequest.failed(ex);return;}try{//看以下会介绍processConnectionRequest(socketChannel, sessionRequest);}catch(finalIOException|SecurityException ex){Closer.closeQuietly(socketChannel);
sessionRequest.failed(ex);}}}}
processConnectionRequest
主要是将channel注册到selector中,便于以上select循环监听读写事件,处理读写事件
privatevoidprocessConnectionRequest(finalSocketChannel socketChannel,finalIOSessionRequest sessionRequest)throwsIOException{validateAddress(sessionRequest.localAddress);validateAddress(sessionRequest.remoteAddress);
socketChannel.configureBlocking(false);prepareSocket(socketChannel.socket());if(sessionRequest.localAddress !=null){finalSocket sock = socketChannel.socket();
sock.setReuseAddress(this.reactorConfig.isSoReuseAddress());
sock.bind(sessionRequest.localAddress);}finalSocketAddress targetAddress;finalIOEventHandlerFactory eventHandlerFactory;if(this.reactorConfig.getSocksProxyAddress()!=null){
targetAddress =this.reactorConfig.getSocksProxyAddress();
eventHandlerFactory =newSocksProxyProtocolHandlerFactory(
sessionRequest.remoteAddress,this.reactorConfig.getSocksProxyUsername(),this.reactorConfig.getSocksProxyPassword(),this.eventHandlerFactory);}else{
targetAddress = sessionRequest.remoteAddress;
eventHandlerFactory =this.eventHandlerFactory;}// Run this under a doPrivileged to support lib users that run under a SecurityManager this allows granting connect permissions// only to this libraryfinalboolean connected;try{
connected =AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>)()-> socketChannel.connect(targetAddress));}catch(finalPrivilegedActionException e){Asserts.check(e.getCause()instanceofIOException,"method contract violation only checked exceptions are wrapped: "+ e.getCause());// only checked exceptions are wrapped - error and RTExceptions are rethrown by doPrivilegedthrow(IOException) e.getCause();}//将socketChannel注册到selector中finalSelectionKey key = socketChannel.register(this.selector,SelectionKey.OP_CONNECT|SelectionKey.OP_READ);finalInternalChannel channel =newInternalConnectChannel(key, socketChannel, sessionRequest,(k, sc, namedEndpoint, attachment)->{finalIOSession ioSession =newIOSessionImpl("c", k, sc);finalInternalDataChannel dataChannel =newInternalDataChannel(
ioSession,
namedEndpoint,
ioSessionDecorator,
sessionListener,
closedSessions);
dataChannel.upgrade(eventHandlerFactory.createHandler(dataChannel, attachment));
dataChannel.setSocketTimeout(reactorConfig.getSoTimeout());return dataChannel;});if(connected){
channel.handleIOEvent(SelectionKey.OP_CONNECT);}else{
key.attach(channel);
sessionRequest.assign(channel);}}