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的方式走一遍以加深印象