深入淺出Netty:accept

佔小狼發表於2016-09-11

本系列:

本章節分析服務端如何accept客戶端的connect請求。

在《深入淺出Netty:NioEventLoop章節中,已經分析了NioEventLoop的工作機制,當有客戶端connect請求,selector可以返回其對應的SelectionKey,方法processSelectedKeys進行後續的處理。

 2184951-d9cb43b57e0dfd11

預設採用優化過的SelectedSelectionKeySet儲存有事件發生的selectedKey。

1、SelectedSelectionKeySet內部使用兩個大小為1024的SelectionKey陣列keysA和keysB儲存selectedKey。

2、把SelectedSelectionKeySet例項對映到selector的原生selectedKeys和publicSelectedKeys。

因為selector的I/O多路複用機制,一次可以返回多個selectedKey,所以要用for迴圈處理全部selectionKey。

假設這時有請求進來,selectedKeys中就存在一個selectionKey,這塊邏輯不清楚的可以回頭看看深入淺出Nio Socket

1、通過k.attachment()可以獲取ServerSocketChannel註冊時繫結上去的附件,其實這個附件就是ServerSocketChannel自身。
2、如果selectedKey的附件是AbstractNioChannel型別的,執行processSelectedKey(k, (AbstractNioChannel) a)方法進行下一步操作。

1、獲取ServerSocketChannel的unsafe物件。
2、當前selectionKey發生的事件是SelectionKey.OP_ACCEPT,執行unsafe的read方法。

該read方法定義在NioMessageUnsafe類中:

1、readBuf 用來儲存客戶端NioSocketChannel,預設一次不超過16個。
2、方法doReadMessages進行處理ServerSocketChannel的accept操作。

1、javaChannel()返回NioServerSocketChannel對應的ServerSocketChannel。
2、ServerSocketChannel.accept返回客戶端的socketChannel 。
3、把 NioServerSocketChannel 和 socketChannel 封裝成 NioSocketChannel,並快取到readBuf。
4、遍歷redBuf中的NioSocketChannel,觸發各自pipeline的ChannelRead事件,從pipeline的head開始遍歷,最終執行ServerBootstrapAcceptor的channelRead方法。

1、child.pipeline().addLast(childHandler)新增childHandler到NioSocketChannel的pipeline。
其中childHandler是通過ServerBootstrap的childHandler方法進行配置的,和NioServerSocketChannel類似,NioSocketChannel在註冊到selector後會觸發其pipeline的fireChannelRegistered方法,並執行initChannel方法,為NioSocketChannel的pipeline新增更多自定義的handler,進行業務處理。
2、childGroup.register(child)將NioSocketChannel註冊到work的eventLoop中,這個過程和NioServerSocketChannel註冊到boss的eventLoop的過程一樣,最終由work執行緒對應的selector進行read事件的監聽。

當readBuf中快取的NioSocketChannel都處理完成後,清空readBuf,並觸發ChannelReadComplete。

到此為止,一次accept流程已經執行完。

END。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

深入淺出Netty:accept

相關文章