手把手教你調(diào)試Netty創(chuàng)建連接流程源碼
? 點(diǎn)擊上方“JavaEdge”,關(guān)注公眾號(hào)
boss thread
NioEventLoop 中的 selector輪詢創(chuàng)建連接事件 (ОР_АССЕРT)
創(chuàng)建 socket channel
初始化 socket channel 并從 worker group 中選擇一個(gè) NioEventLoop
worker thread
將socket channel注冊(cè)到選擇的NioEventLoop的selector
注冊(cè)讀事件(OP_ READ)到selector 上
接收連接請(qǐng)求的處理本質(zhì)是對(duì) OP_ACCEPT 的處理,即在 NioEventLoop 中,因?yàn)樽?cè)到了NioEventLoop的 selector。
分別調(diào)試啟動(dòng) EchoServer 和 EchoClient
跳至對(duì)應(yīng) handler

當(dāng)前為 bosseventloop,不是 workereventloop
所以這里 false,又來到注冊(cè)



創(chuàng)建完連接后了,已經(jīng)可以開始接收數(shù)據(jù)了,即準(zhǔn)備讀數(shù)據(jù)了

最后觀察下 server 的日志信息
前5行都是服務(wù)啟動(dòng),后面的就是為了創(chuàng)建連接

服務(wù)啟動(dòng)過程多了個(gè) bind 過程,且只綁定了一個(gè)接口,而對(duì)于下面的創(chuàng)建連接過程它有兩個(gè)端口:客戶端端口+server 監(jiān)聽的端口,這就是 socketChannel
接收連接的核心代碼
// 阻塞輪詢。非阻塞輪詢。超時(shí)等待輪詢selector.select()/ selectNow()/select(timeoutMillis) 發(fā)現(xiàn) OP_ACCEPT 事件,處理:SocketChannel socketChannel = serverSocketChannel.accept()selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);selectionKey.interestOps(OP_READ);
創(chuàng)建連接的初始化和注冊(cè)是通過pipeline.fireChannelRead在ServerBootstrapAcceptor中完成
第一次Register并非監(jiān)聽OP_READ,而是0
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this)最終監(jiān)聽OP_READ是通過"Register"完成后的fireChannelActive
(io.netty.channel.AbstractChannel.AbstractUnsafe#register0)觸發(fā)
Worker’s NioEventLoop是通過Register操作執(zhí)行來啟動(dòng)。
接受連接的讀操作,不會(huì)嘗試讀取更多次(16次)。
因?yàn)闊o法知道后續(xù)是否還有連接,不可能一直嘗試。
往期推薦

目前交流群已有?800+人,旨在促進(jìn)技術(shù)交流,可關(guān)注公眾號(hào)添加筆者微信邀請(qǐng)進(jìn)群
喜歡文章,點(diǎn)個(gè)“在看、點(diǎn)贊、分享”素質(zhì)三連支持一下~
