Netty source code analysis --Channel register & bind port (under) (vii)

      Next, we see that two very important ways

      

      Is processSelectedKeys () and runAllTasks () method has.

      selectionKey ready in the event, such as accept, connect, read, write, etc., triggered by processSelectedKeys method. Belonging to the I / O tasks.

      Add to taskQueue tasks, such as register0, bind0 other tasks, triggered by runAllTasks method. Is a non-I / O tasks.

      Both tasks execution time ratio is controlled by the variable ioRatio, default is 50, it means that allow non-IO task execution time equal to the time the IO tasks performed.

      We look processSelectedKeys () method, because selectedKeys! = Null so enter processSelectedKeysOptimized () method.

      In the absence of here just start the server, no client access to come in, so let's skip processSelectedKeys (), we will be a combination of the client in terms of access here.

      Look directly runAllTasks () method.

      

        Runnable task = pollTask ​​(); This is a task out of the taskQueue.

        Then loop to perform this task, safeExecute (task).

        

       This method is also very simple, direct execution run () method Runnable interface (not here to start a thread, but performs only an ordinary run method).

       Here's what we think about this task should be?

        

        Also remember this code? It is this register0 () method.

       

         We first enter the doRegister () method

         

         继续传入当前的eventloop中的selector, opt = 0,  第三个参数 this 就是当前的 NioServerSocketChannel。 进入register 方法

        

           大家看我圈出来的这一句,熟悉吗?我当时将NIO的时候是不是讲到了。

           这里就是把当前的channel注册到这个多路复用器上。并且把 NioServerSocketChannel 传进去当做附件 attach, 注册的 interestOps = 0 

          好了,当执行完task,由于是一个死循环,那么会继续执行刚刚的整个过程。

         

           好了,总结一下: 也就是说有一个线程一直在这里不断循环的等待新的 selectionKey中ready的事件,如accept、connect、read、write等。 如果有待处理的task,将会去优先处理的task.

           一会我们会启动一个客户端看一下是怎么交互的。

           整个注册完成之后,接下来就是 绑定端口 ,将服务对外开放出去。

           我们看下AbstractBootstrap中的  doBind() 方法。

            

              由于整个注册过程是异步的,所以这里 regFuture.isDone() 是否已经完成,如果完成直接执行doBind0(),如果没有完成,那么就监听异步响应方法,等待成功之后,再执行doBind0()方法。

             我们进入doBind0()方法

             

           我们看其实就是向eventLoop中的任务队列中添加一个task。

           这里我们debug来看一下

          另外在 AbstractBootstrap中打一个断点,在这里等待注册事件先完成。

          

         好的,我们启动服务端。

         

        断点进来了, 我们再在  NioEventLoop 中打一个断点,因为这里是处理task的地方

           

           我们发现有一个主线程,一个子线程,如下图

          

         切换到子线程,我们看下 task 的执行过程。

         

       因为switch中的hasTask() 是true,那么我们就直接看

       

       

     从任务队列中取出一个task,我们看到就是刚刚我们的那个任务。然后通过safeExecute(task)执行run方法

      

      继续F5。我们看进入到了runnable中的run方法。

   

     接下来就是一段链式调用,链式访问pipleline中的handler         TailContext -> ServerBootstrapAcceptor -> LoggingHandler -> HeadContext

     

     TailContext 和 ServerBootstrapAcceptor 中没有bind方法,直接进入LoggingHandler的bind方法,打一个日志

    

   继续f5进入到 HeadContext中的bind方法

  

  

   先判断是否激活,如果没有,则稍后链式调用handlers中的 channelActive()方法。

   进入doBind方法

   

   ok,到这里绑定端口成功。

  目前为止,Server服务端启动完成,接下来我们看一下,一个客户端是怎么接入进来并且进行读写操作的。

Guess you like

Origin www.cnblogs.com/huxipeng/p/11075097.html