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