Netty源码解读------------客户端接入绑定(二)
来源:互联网 发布:淘宝发快递一般多少钱 编辑:程序博客网 时间:2024/06/08 07:50
下面接着看下面这段代码
//Binder里面的代码 public void channelOpen( ChannelHandlerContext ctx, ChannelStateEvent evt) { try { evt.getChannel().getConfig().setPipelineFactory(getPipelineFactory()); // Split options into two categories: parent and child. Map<String, Object> allOptions = getOptions(); Map<String, Object> parentOptions = new HashMap<String, Object>(); for (Entry<String, Object> e: allOptions.entrySet()) { if (e.getKey().startsWith("child.")) { childOptions.put( e.getKey().substring(6), e.getValue()); } else if (!e.getKey().equals("pipelineFactory")) { parentOptions.put(e.getKey(), e.getValue()); } } // Apply parent options. evt.getChannel().getConfig().setOptions(parentOptions); } finally { ctx.sendUpstream(evt); }//evt.getChannel().bind()这里开始调用绑定本地接口, 进入里面看下面的情况 boolean finished = futureQueue.offer(evt.getChannel().bind(localAddress)); assert finished; }
public static ChannelFuture bind(Channel channel, SocketAddress localAddress) { if (localAddress == null) { throw new NullPointerException("localAddress"); } ChannelFuture future = future(channel); //像pipeline发送一个bound消息, 里面存储本地地址, 接着看里面的写法。 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent( channel, future, ChannelState.BOUND, localAddress)); return future; }
//DefaultPipeLine.java public void sendDownstream(ChannelEvent e) { DefaultChannelHandlerContext tail = getActualDownstreamContext(this.tail); if (tail == null) { try { //getSink() 这个sink是在channel里面放入的NioServerSocketPipelineSink, 里面还放了NioWorker,嘿嘿 getSink().eventSunk(this, e); return; } catch (Throwable t) { notifyHandlerException(e, t); return; } } sendDownstream(tail, e); }
//NioServerSocketPipelineSink.java 进入这个里面 private void handleServerSocket(ChannelEvent e) { if (!(e instanceof ChannelStateEvent)) { return; } ChannelStateEvent event = (ChannelStateEvent) e; NioServerSocketChannel channel = (NioServerSocketChannel) event.getChannel(); ChannelFuture future = event.getFuture(); ChannelState state = event.getState(); Object value = event.getValue(); switch (state) { case OPEN: if (Boolean.FALSE.equals(value)) { close(channel, future); } break; case BOUND: if (value != null) { //进入这个方法里面, 进行接口的绑定 bind(channel, future, (SocketAddress) value); } else { close(channel, future); } break; } } private void bind( NioServerSocketChannel channel, ChannelFuture future, SocketAddress localAddress) { boolean bound = false; boolean bossStarted = false; try { //socket绑定bind channel.socket.socket().bind(localAddress, channel.getConfig().getBacklog()); bound = true; future.setSuccess(); //触发bound事件 fireChannelBound(channel, channel.getLocalAddress()); Executor bossExecutor = ((NioServerSocketChannelFactory) channel.getFactory()).bossExecutor; //它的作用是将bossExecutor 和Boss绑定在一起。 DeadLockProofWorker.start( bossExecutor, new ThreadRenamingRunnable( //主要看new Boss()这个里面的实现 new Boss(channel), "New I/O server boss #" + id + " (" + channel + ')')); bossStarted = true; } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (!bossStarted && bound) { close(channel, future); } } }
//Boss.java Boss(NioServerSocketChannel channel) throws IOException { //channel是netty封装的一成NioServerChannel this.channel = channel; //打开一个选择,nio里面的东西。 选择器 selector = Selector.open(); //标志 boolean registered = false; try { // channel.socket 是nio里面的NioServerChannel里面的东西, register注册accept事件, 一有客户连接上来进去在selector能找到。 channel.socket.register(selector, SelectionKey.OP_ACCEPT); registered = true; } finally { if (!registered) { closeSelector(); } } //嘿嘿, 记住这里把selector放进去了。 channel.selector = selector; } //上面的DeadLockProofWorker.start()有启动这个线程 public void run() { final Thread currentThread = Thread.currentThread(); //这里使用锁, 来防止高并发 channel.shutdownLock.lock(); try { for (;;) { try { if (selector.select(1000) > 0) { selector.selectedKeys().clear(); } //接收客户端socket, 当客户端有连入时,这里会记录 SocketChannel acceptedSocket = channel.socket.accept(); if (acceptedSocket != null) {//注册接入进来的客户端 registerAcceptedChannel(acceptedSocket, currentThread); } } catch (SocketTimeoutException e) { // Thrown every second to get ClosedChannelException // raised. } catch (CancelledKeyException e) { // Raised by accept() when the server socket was closed. } catch (ClosedSelectorException e) { // Raised by accept() when the server socket was closed. } catch (ClosedChannelException e) { // Closed as requested. break; } catch (Throwable e) { logger.warn( "Failed to accept a connection.", e); try { Thread.sleep(1000); } catch (InterruptedException e1) { // Ignore } } } } finally { channel.shutdownLock.unlock(); closeSelector(); } } private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) { try { ChannelPipeline pipeline =//channel.getConfig()放入的 是我们自己重新的方法.这一段,所以里面的getPipeline()就把我们直接写的handler嵌入进来了。 /* bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ServerHandler()); } });*/ channel.getConfig().getPipelineFactory().getPipeline(); NioWorker worker = nextWorker(); //从这里进入 worker.register(new NioAcceptedSocketChannel( channel.getFactory(), pipeline, channel, NioServerSocketPipelineSink.this, acceptedSocket, worker, currentThread), null); } catch (Exception e) { logger.warn( "Failed to initialize an accepted socket.", e); try { acceptedSocket.close(); } catch (IOException e2) { logger.warn( "Failed to close a partially accepted socket.", e2); } } }
//NioWorker.java void register(NioSocketChannel channel, ChannelFuture future) { boolean server = !(channel instanceof NioClientSocketChannel); //channel是和registerTask关联的, 没一个客户端连接都会绑定一个线程。 Runnable registerTask = new RegisterTask(channel, future, server); //临时选择器 Selector selector; synchronized (startStopLock) { //注意这里, 这里只会执行一次if里面的代码 if (!started) { // Open a selector if this worker didn't start yet. try { //选择器 this.selector = selector = Selector.open(); } catch (Throwable t) { throw new ChannelException( "Failed to create a selector.", t); } // Start the worker thread with the new Selector. String threadName = (server ? "New I/O server worker #" : "New I/O client worker #") + bossId + '-' + id; boolean success = false; try { DeadLockProofWorker.start( executor, new ThreadRenamingRunnable(this, threadName)); success = true; } finally { if (!success) { // Release the Selector if the execution fails. try { selector.close(); } catch (Throwable t) { logger.warn("Failed to close a selector.", t); } this.selector = selector = null; // The method will return to the caller at this point. } } } else { // Use the existing selector if this worker has been started. selector = this.selector; } assert selector != null && selector.isOpen(); started = true; //把注册的任务放入到 registerTaskQueue里面 boolean offered = registerTaskQueue.offer(registerTask); assert offered; } if (wakenUp.compareAndSet(false, true)) { selector.wakeup(); } }
今天就暂时说到这里, 有什么不明白的。可以问我。
0 0
- Netty源码解读------------客户端接入绑定(二)
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读(二)Netty中的buffer
- Netty源码解读
- Netty源码解读Promise
- Netty源码解读EventExecutorGroup
- Netty源码解读DefaultPromise
- Netty源码分析(二)—客户端初始化
- Netty源码解读 Netty中的buffer
- Netty源码解读之线程
- Netty源码解读之线程
- Netty中的Future源码解读
- netty源码分析(二十三)ReplayingDecoder源码分析与特性解读以及其他编解码器介绍
- 添加侧滑手势返回上一级界面
- 自制作数据上的pva faster rcnn 训练
- java后台解析json字符串
- 2D 横幅过关游戏 Frogatto
- ls和rm管道符删除文件
- Netty源码解读------------客户端接入绑定(二)
- Could not Open Install.Log File解决方法
- java线程状态——死锁
- C#中调用CMD命令行截取输出流的范例
- LeetCode-19. Remove Nth Node From End of List
- Android之源码之模块编译调试
- WebView交互传递json字符串并解析
- servlet的一个小项目(四)
- 继续自己的第一个swift项目的奋斗之路!