netty源码解解析(4.0)-3 Channel的抽象实现
生活随笔
收集整理的這篇文章主要介紹了
netty源码解解析(4.0)-3 Channel的抽象实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
AbstractChannel和AbstractUnsafe抽象類 io.netty.channel.AbstractChannel 從本章開(kāi)始,會(huì)有大量的篇幅涉及到代碼分析。為了能夠清晰簡(jiǎn)潔的地說(shuō)明代碼的結(jié)構(gòu)和功能,我會(huì)用代碼注釋+獨(dú)立段落的方式加以呈現(xiàn)。 所以,為你能更好地理解代碼,請(qǐng)不要忽略代碼中黑體字注釋。 AbstractChannel和AbstractUnsafe之間的關(guān)系 AbstractChannel實(shí)現(xiàn)了Channel接口,AbstractUnsafe實(shí)現(xiàn)了Unsafe。這兩個(gè)類是抽象類,他們實(shí)現(xiàn)了Channel和Unsafe的絕大部分接口。在AbstractChannel的實(shí)現(xiàn)中,每個(gè)方法都會(huì)直接或間接調(diào)用Unsafe對(duì)應(yīng)的同名方法。所有的inbound和outbound方法都是通過(guò)pipeline間接調(diào)用,其他的輔助方法直接使用unsafe實(shí)例調(diào)用。pipline和unsafe實(shí)例在AbstractChannel的構(gòu)造方法創(chuàng)建: protected AbstractChannel(Channel parent) { this.parent = parent; unsafe = newUnsafe(); //AbstractChannel沒(méi)有實(shí)現(xiàn)這個(gè)方法 pipeline = newChannelPipeline(); // newChannelPipline的實(shí)現(xiàn) return new DefaultChannelPipeline(this); } 直接調(diào)用的例子: @Override public SocketAddress localAddres) { SocketAddress localAddress = this.localAddress; if (localAddress == null) { try { //這里直接調(diào)用了Unsafe的localAddress()方法 this.localAddress = localAddress = unsafe().localAddress(); } catch (Throwable t) { // Sometimes fails on a closed socket in Windows. return null; } } return localAddress; } 間接調(diào)用的例子 @Override public ChannelFuture bind(SocketAddress localAddress) { return pipeline.bind(localAddress); //通過(guò)pipline間接調(diào)用Unsafe的bind方法 } 關(guān)于pipline是怎樣調(diào)用Unsafe方法的,會(huì)在后面的Pipline相關(guān)章節(jié)詳細(xì)分析,這里只需記住。pipeline所有方法調(diào)用最終都會(huì)(如果沒(méi)有改變ChannelContextHandler的默認(rèn)實(shí)現(xiàn))通過(guò)使用newUnsafe創(chuàng)建的Unsafe實(shí)例調(diào)用Unsafe的同名方法(如果有的話)。 netty給出這一對(duì)Abstract實(shí)現(xiàn)有兩個(gè)目的: 把channel和eventLoop綁定,eventLoop線程就是I/O線程。 確保真正的register操作在I/O線程中執(zhí)行。 確保每個(gè)channel的register操作只執(zhí)行一次。 真正的register操作執(zhí)行成功后, 觸發(fā)channelRegistered事件,如果channel此時(shí)仍處于active狀態(tài),觸發(fā)channelActive事件,并確保這些事件只觸發(fā)一次。 真正的register操作執(zhí)行成功后, 如果channel此時(shí)仍處于active狀態(tài),并且channel的配置支持autoRead, 則執(zhí)行beginRead操作,讓eventLoop可以自動(dòng)觸發(fā)channel的read事件。 bind實(shí)現(xiàn) @Override public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { assertEventLoop(); if (!promise.setUncancellable() || !ensureOpen(promise)) { return; } // See: https://github.com/netty/netty/issues/576 if (Boolean.TRUE.equals(config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress) localAddress).getAddress().isAnyLocalAddress() && !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) { // Warn a user about the fact that a non-root user can't receive a // broadcast packet on *nix if the socket is bound on non-wildcard address. logger.warn( "A non-root user can't receive a broadcast packet if the socket " + "is not bound to a wildcard address; binding to a non-wildcard " + "address (" + localAddress + ") anyway as requested."); } //先保存是否active的狀態(tài) boolean wasActive = isActive(); try { doBind(localAddress); //調(diào)用doBind, 需要子類實(shí)現(xiàn)這個(gè)方法完成真正的bind操作 } catch (Throwable t) { safeSetFailure(promise, t); closeIfClosed(); return; } if (!wasActive && isActive()) { //如果執(zhí)行完doBind后從非active狀態(tài)變成active裝,則觸發(fā)channelActive事件 invokeLater(new Runnable() { @Override public void run() { pipeline.fireChannelActive(); } }); } safeSetSuccess(promise); } bind語(yǔ)義:
- 進(jìn)一步明確接口的語(yǔ)意。
- 簡(jiǎn)化Channel接口的實(shí)現(xiàn)。
- 調(diào)用抽象方法doBind, 它需要子類實(shí)現(xiàn)。
- 如果channel的狀態(tài)從非active變成active狀態(tài),則觸發(fā)channelActive事件
- 調(diào)用doDeregister執(zhí)行真正的deregister操作
- 根據(jù)參數(shù)可能需要觸發(fā)channelInactive事件
- 觸發(fā)channelUnregistered事件
- 調(diào)用doWrite方法執(zhí)行真正的寫(xiě)操作
- 如果寫(xiě)操作失敗,調(diào)用close或者shutdownOutput進(jìn)行善后。
| 方法 | 說(shuō)明 |
| protected abstract SocketAddress localAddress0() | 被localAddress調(diào)用,執(zhí)行真正的獲取本地地址的操作。 |
| protected abstract SocketAddress remoteAddress0() | 被remoteAddress調(diào)用,是真正的獲取遠(yuǎn)程地址的操作。 |
| protected abstract boolean isCompatible(EventLoop loop) | 檢查eventLoop是是否和這個(gè)Channel兼容。 |
| protected void doRegister() | 調(diào)用鏈register->register0->doRegister, 真正的注冊(cè)操作。 |
| protected abstract void doBind(SocketAddress localAddress) | 被bind調(diào)用,執(zhí)行真正綁定本地地址的操作。 |
| protected abstract void doDisconnect() | 被disconnect調(diào)用,執(zhí)行真正的斷開(kāi)連接操作。 |
| protected abstract void doClose() | 被close掉,執(zhí)行真正的關(guān)閉channel操作。 |
| protected void doShutdownOutput() | 被shutdownOutput調(diào)用,用來(lái)關(guān)閉output通道,使Channel不能write。它的的默認(rèn)實(shí)現(xiàn)是調(diào)用doClose |
| protected void doDeregister() | 被deregister調(diào)用,是真正的注銷操作,雖然不是抽象方法,然而只有一個(gè){}, 還是要等你來(lái)搞定。 |
| protected abstract void doBeginRead() | 調(diào)用鏈register->register0->beginRead->doBeginRead, 實(shí)現(xiàn)讓eventLoop可以自動(dòng)觸發(fā)read事件。 |
| protected abstract void doWrite(ChannelOutboundBuffer in) | 調(diào)用鏈flush->flush0->doWrite, 執(zhí)行真正的寫(xiě)操作。 |
| protected Object filterOutboundMessage(Object msg) | 被write調(diào)用,在消息被放到outboundBuffer之前對(duì)消息進(jìn)行處理,默認(rèn)啥事都沒(méi)干,就是把你傳進(jìn)去的msg還給你。 |
轉(zhuǎn)載于:https://www.cnblogs.com/brandonli/p/9949730.html
總結(jié)
以上是生活随笔為你收集整理的netty源码解解析(4.0)-3 Channel的抽象实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。