Netty 學(xué)習(xí)(八):新連接接入源碼說明作者: Grey
原文地址:
博客園:Netty 學(xué)習(xí)(八):新連接接入源碼說明
CSDN:Netty 學(xué)習(xí)(八):新連接接入源碼說明
新連接的接入分為3個過程
- 檢測到有新連接 。
- 將新連接注冊到 worker 線程 。
- 注冊新連接的讀事件 。
NioEventLoop中的processSelectedKey()方法中private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {......final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();......// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead// to a spin loopif ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {unsafe.read();}.....}啟動一個 Netty 服務(wù)端和 Netty 客戶端,在unsafe.read()這一行打斷點(diǎn),可以得到這里的unsafe就是NioMessageUnsafe,進(jìn)入NioMessageUnsafe的read()方法,這個方法主要做的事情就是:創(chuàng)建,設(shè)置并綁定
NioSocketChannel 。private final List<Object> readBuf = new ArrayList<Object>();@Overridepublic void read() {......do {// 創(chuàng)建`NioSocketChannel`int localRead = doReadMessages(readBuf);......} while (continueReading(allocHandle));......// 設(shè)置并綁定 NioSocketChannelint size = readBuf.size();for (int i = 0; i < size; i ++) {readPending = false;pipeline.fireChannelRead(readBuf.get(i));}readBuf.clear();allocHandle.readComplete();pipeline.fireChannelReadComplete();......}}創(chuàng)建NioSocketChannel調(diào)用的是doReadMessages()方法,通過Debug,可以看到doReadMessage()來自于NioServerSocketChannel中@Overrideprotected int doReadMessages(List<Object> buf) throws Exception {SocketChannel ch = SocketUtils.accept(javaChannel());try {if (ch != null) {buf.add(new NioSocketChannel(this, ch));return 1;}} catch (Throwable t) {logger.warn("Failed to create a new channel from an accepted socket.", t);try {ch.close();} catch (Throwable t2) {logger.warn("Failed to close a socket.", t2);}}return 0;}可以看到此時調(diào)用的是 Java 底層的accept()方法,創(chuàng)建了一條 JDK 層面的Channel, Netty 將其封裝成自定義的NioSocketChannel,并加入一個List 。繼續(xù) Debug,進(jìn)入 NioSocketChannel 的構(gòu)造方法中,調(diào)用的是
AbstractNioByteChannel的構(gòu)造方法protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {super(parent, ch, SelectionKey.OP_READ);}這個方法類似在 NIO 編程中,注冊 OP_READ 事件,表示 Channel 對讀事件感興趣 。【八 Netty 學(xué)習(xí):新連接接入源碼說明】接下來是設(shè)置并綁定
NioSocketChannel,處理每個NioSocketChannel,通過 Debug 可以來到AbstractUnsafe的register0()方法private void register0(ChannelPromise promise) {// 注冊SelectordoRegister();// 執(zhí)行 handlerpipeline.invokeHandlerAddedIfNeeded();// 傳播 ChannelRegistered事件pipeline.fireChannelRegistered();// 注冊讀事件if (isActive()) {if (firstRegistration) {pipeline.fireChannelActive();} else if (config().isAutoRead()) {// This channel was registered before and autoRead() is set. This means we need to begin read// again so that we process inbound data.//// See https://github.com/netty/netty/issues/4805beginRead();}}}這個方法主要完成的事情就是:- 將
NioSocketChannel注冊到Selector上
- 配置自定義的
Handler。
- 將連接注冊事件傳播下去,調(diào)用了每個
Handler的channelRegistered方法 。經(jīng)驗(yàn)總結(jié)擴(kuò)展閱讀
- 紫媽是什么意思
- 高中物理好的學(xué)習(xí)方法
- 學(xué)習(xí)記錄-Python的局部變量和全局變量
- 如何讓差生學(xué)習(xí)好英語
- 2022年臘月初八喬遷新居好嗎
- 初等數(shù)論學(xué)習(xí)筆記 III:數(shù)論函數(shù)與篩法
- 為什么有些人會孤立認(rèn)真學(xué)習(xí)的人
- 為什么西晉會發(fā)生八王之亂
- 蘋果ipad分屏功能怎么使用(ipad 9可以分屏學(xué)習(xí)嗎)
- 前端程序員學(xué)習(xí) Golang gin 框架實(shí)戰(zhàn)筆記之一開始玩 gin
