1. 程式人生 > >Netty原始碼分析第3章(客戶端接入流程)---->第5節: 監聽讀事件

Netty原始碼分析第3章(客戶端接入流程)---->第5節: 監聽讀事件

 

Netty原始碼分析第三章: 客戶端接入流程

 

第五節: 監聽讀事件

 

我們回到AbstractUnsafe的register0()方法:

private void register0(ChannelPromise promise) {
    try {
        //省略程式碼
        //做實際的註冊
        doRegister();
        neverRegistered = false;
        registered = true;
        //觸發事件
        pipeline.invokeHandlerAddedIfNeeded();
        safeSetSuccess(promise);
        
//觸發註冊成功事件 pipeline.fireChannelRegistered(); if (isActive()) { if (firstRegistration) { //傳播active事件(4) pipeline.fireChannelActive(); } else if (config().isAutoRead()) { beginRead(); } } } catch
(Throwable t) { //省略程式碼 } }

doRegister()做完實際的註冊之後, 會走到if (isActive())這個判斷, 因為這個時候鏈路已經完成, 所以這裡是true, 預設判斷條件if (firstRegistration)也為true, 所以這裡會走到pipeline.fireChannelActive()這一步

有關pipeline我們會在下一章進行詳細分析, 這裡我們只需要知道, 最後會流轉到AbstractUnsafe的beginRead()方法

跟到beginRead()方法:

public final void
beginRead() { assertEventLoop(); if (!isActive()) { return; } try { doBeginRead(); } catch (final Exception e) { //程式碼省略 } }

這塊程式碼同樣我們也不陌生, 因為我們分析NioServerSocketChannel也分析過了這一步

我們繼續跟到doBeginRead():

protected void doBeginRead() throws Exception {
    //拿到selectionKey
    final SelectionKey selectionKey = this.selectionKey;
    if (!selectionKey.isValid()) {
        return;
    }
    readPending = true;
    //獲得感興趣的事件
    final int interestOps = selectionKey.interestOps();
    //判斷是不是對任何事件都不監聽
    if ((interestOps & readInterestOp) == 0) {
        //此條件成立
        //將之前的accept事件註冊, readInterest代表可以讀取一個新連線的意思
        selectionKey.interestOps(interestOps | readInterestOp);
    }
}

這段程式碼相信大家會比較熟悉, 因為我們服務端channel註冊完之後也走到了這裡

因為我們在建立NioSocketChannel的時候初始化的是read事件, selectionKey是channel在註冊時候返回的key, 所以selectionKey.interestOps(interestOps | readInterestOp)這一步, 會將當前channel的讀事件註冊到selector中去

註冊完成之後, NioEventLoop就可以輪詢當前channel的讀事件了

以上就是NioSocketChannel註冊監聽事件的流程

 

 

第三章總結

    本章學習了有關客戶端接入, NioSocketChannel的建立, 註冊等相關操作, 並且涉及到了上一小節剖析的eventLoop的相關邏輯, 同學們可以將相關的流程通過debug的方式走一遍以加深印象