Netty服務端Channel注冊Selector及綁定服務器端口


一 服務端Channel注冊Selector

當服務端Channel 創建並且初始化完成之后,會將其注冊到 selector,通過語句config().group().register(channel)進行注冊工作,該方法最終調用 AbstractUnsafe 類的 register 方法。以下各圖是服務端Channel注冊到Selector上的函數調用鏈。
 
 
 
 
 
 
截止到此,服務器Channel雖然已經注冊到了Selector,但是注冊時配置的感興趣的事件時0,可以看看doRegister()方法:
 
而且,這里服務端Channel也還沒有綁定服務器的端口,只是完成了注冊工作,下面看一下綁定服務端端口的操作。

二 服務端Channel綁定服務器端口

服務端Channel的綁定工作是在AbstractBootstrap的doBind0()方法中完成的:
 
 
在AbstractBootstrap的doBind0()方法中,給服務端Channel已經綁定的NioEventLoop中添加了一個Runnable任務,這個任務中實現了服務端Channel綁定服務器端口的工作。那NioEventLoop是什么時候去執行這個任務的?這里先說一下NioEventLoop的職責,它主要做兩件事:①處理Channel中已經准備就緒的IO事件;②處理在任務隊列中的非IO任務。服務端Channel綁定服務器的端口就屬於一個非IO任務。並且NioEventLoop在處理IO事件與非IO任務時,可以根據ioRatio這個成員變量來分配處理IO事件與非IO任務的時間,默認情況ioRatio是50,說明分配給兩者的處理時間是一樣的。下面就是NioEventLoop啟動后處理IO事件與非IO任務的代碼,在NioEventLoop類的run方法中,由以下代碼可知,在服務端的NioEventLoop啟動之前,已經將綁定端口的任務添加到了任務隊列,進到下面的for循環時,因為隊列中有任務且還沒有綁定服務器的端口,將執行selectNow方法並且直接返回,在switch中什么也不干,因此在調用processSelectedKeys方法后因為沒有准備就緒的IO事件所以也直接返回,然后執行任務隊列中的任務,完成服務器端口的綁定工作。
for (;;) {
    // 當taskQueue中有任務時,使用非阻塞的selectNow方法來獲取Channel中准備就緒的IO事件
    // 如果Channel中沒有准備就緒的IO事件,selectNow可以快速返回,然后處理taskQueue中的任務
    switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
        case SelectStrategy.CONTINUE:
            continue;
        case SelectStrategy.SELECT:
            select(wakenUp.getAndSet(false));
        default:
    }
    cancelledKeys = 0;
    needsToSelectAgain = false;
    final int ioRatio = this.ioRatio;
    if (ioRatio == 100) {
        try {
            processSelectedKeys();
        } finally {
            // Ensure we always run tasks.
            // 處理在任務隊列中的非IO任務
            runAllTasks();
        }
    } else {
        final long ioStartTime = System.nanoTime();
        try {
            processSelectedKeys();
        } finally {
            // Ensure we always run tasks.
            final long ioTime = System.nanoTime() - ioStartTime;
            runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
        }
    }

至此,服務端Channel不僅創建、初始化完成,也注冊到了Selector,並且綁定了服務端端口,在這之后,服務器便可以接收客戶端的連接並進行處理了。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM