日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Netty4學(xué)習(xí)筆記(1)

 王慶峰 2015-06-19

Netty4

Netty是一個(gè)和MINA類似的Java NIO框架,目前的最新版本是4.0.13,這兩個(gè)框架的主要作者好像都是同一個(gè)韓國人


Channel

Channel是Netty最核心的接口,一個(gè)Channel就是一個(gè)聯(lián)絡(luò)Socket的通道,通過Channel,你可以對(duì)Socket進(jìn)行各種操作。


ChannelHandler

用Netty編寫網(wǎng)絡(luò)程序的時(shí)候,你很少直接操縱Channel,而是通過ChannelHandler來間接操縱Channel。


ChannelPipeline

ChannelPipeline實(shí)際上應(yīng)該叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一個(gè)ChandlerHandler的鏈表,當(dāng)需要對(duì)Channel進(jìn)行某種處理的時(shí)候,Pipeline負(fù)責(zé)依次調(diào)用每一個(gè)Handler進(jìn)行處理。每個(gè)Channel都有一個(gè)屬于自己的Pipeline,調(diào)用Channel#pipeline()方法可以獲得Channel的Pipeline,調(diào)用Pipeline#channel()方法可以獲得Pipeline的Channel。

ChannelPipeline的方法有很多,其中一部分是用來管理ChannelHandler的,如下面這些:

  1. ChannelPipeline addFirst(String name, ChannelHandler handler);  
  2. ChannelPipeline addLast(String name, ChannelHandler handler);  
  3. ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);  
  4. ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);  
  5. ChannelPipeline remove(ChannelHandler handler);  
  6. ChannelHandler remove(String name);  
  7. ChannelHandler removeFirst();  
  8. ChannelHandler removeLast();  
  9. ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);  
  10. ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);  
  11. ChannelHandler first();  
  12. ChannelHandler last();  
  13. ChannelHandler get(String name);  

根據(jù)上面的方法,能夠大概想象的到Pipeline按照什么樣的方式組織Handler。

ChannelHandlerContext

ChannelPipeline并不是直接管理ChannelHandler,而是通過ChannelHandlerContext來間接管理,這一點(diǎn)通過ChannelPipeline的默認(rèn)實(shí)現(xiàn)DefaultChannelPipeline可以看出來。

調(diào)用ChannelHandlerContext#channel()方法可以得到和Context綁定的Channel,調(diào)用ChannelHandlerContext#handler()方法可以得到和Context綁定的Handler。


ChannelPipeline和ChannelHandlerContext默認(rèn)實(shí)現(xiàn)

DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默認(rèn)實(shí)現(xiàn),下面是它們的部分代碼:

  1. final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {  
  2.   
  3.     volatile DefaultChannelHandlerContext next;  
  4.     volatile DefaultChannelHandlerContext prev;  
  5.   
  6.     private final boolean inbound;  
  7.     private final boolean outbound;  
  8.     private final AbstractChannel channel;  
  9.     private final DefaultChannelPipeline pipeline;  
  10.     private final String name;  
  11.     private final ChannelHandler handler;  
  12.     private boolean removed;  
  13.   
  14.     // ...  
  15. }  
  1. final class DefaultChannelPipeline implements ChannelPipeline {  
  2.     // ...  
  3.   
  4.     final DefaultChannelHandlerContext head;  
  5.     final DefaultChannelHandlerContext tail;  
  6.   
  7.     // ...  
  8. }  

從上面的代碼可以看出,在DefaultPipeline內(nèi)部,DefaultChannelHandlerContext組成了一個(gè)雙向鏈表:

再來看看DefaultChannelPipeline的構(gòu)造函數(shù):

  1. public DefaultChannelPipeline(AbstractChannel channel) {  
  2.     if (channel == null) {  
  3.         throw new NullPointerException("channel");  
  4.     }  
  5.     this.channel = channel;  
  6.   
  7.     TailHandler tailHandler = new TailHandler();  
  8.     tail = new DefaultChannelHandlerContext(thisnull, generateName(tailHandler), tailHandler);  
  9.   
  10.     HeadHandler headHandler = new HeadHandler(channel.unsafe());  
  11.     head = new DefaultChannelHandlerContext(thisnull, generateName(headHandler), headHandler);  
  12.   
  13.     head.next = tail;  
  14.     tail.prev = head;  
  15. }  

可以看到,DefaultChinnelPipeline內(nèi)部使用了兩個(gè)特殊的Handler來表示Handler鏈的頭和尾:


ChannelHandler的種類

從上面DefaultChannelHandlerContext代碼可以知道,Handler實(shí)際上分為兩種,Inbound和Outbound,這一點(diǎn)也可以從ChannelHandler接口的子接口得到證明:

  1. public interface ChannelInboundHandler extends ChannelHandler {  
  2.   // ...  
  3. }  
  4.   
  5. public interface ChannelOutboundHandler extends ChannelHandler {  
  6.   // ...  
  7. }  

事件的傳播

為了搞清楚事件如何在Pipeline里傳播,讓我們從Channel的抽象子類AbstractChannel開始,下面是AbstractChannel#write()方法的實(shí)現(xiàn):

  1. public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {  
  2.     // ...  
  3.     @Override  
  4.     public Channel write(Object msg) {  
  5.         return pipeline.write(msg);  
  6.     }  
  7.     // ...  
  8. }  

AbstractChannel直接調(diào)用了Pipeline的write()方法:


再看DefaultChannelPipeline的write()方法實(shí)現(xiàn):

  1. final class DefaultChannelPipeline implements ChannelPipeline {  
  2.     // ...  
  3.     @Override  
  4.     public ChannelFuture write(Object msg) {  
  5.         return tail.write(msg);  
  6.     }  
  7.     // ...  
  8. }  

因?yàn)閣rite是個(gè)outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,調(diào)用其write()方法:


接著看DefaultChannelHandlerContext的write()方法:

  1. final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {  
  2.     // ...  
  3.     @Override  
  4.     public ChannelFuture write(Object msg) {  
  5.         return write(msg, newPromise());  
  6.     }  
  7.   
  8.     @Override  
  9.     public ChannelFuture write(final Object msg, final ChannelPromise promise) {  
  10.         if (msg == null) {  
  11.             throw new NullPointerException("msg");  
  12.         }  
  13.   
  14.         validatePromise(promise, true);  
  15.   
  16.         write(msg, false, promise);  
  17.   
  18.         return promise;  
  19.     }  
  20.   
  21.     private void write(Object msg, boolean flush, ChannelPromise promise) {  
  22.         DefaultChannelHandlerContext next = findContextOutbound();  
  23.         next.invokeWrite(msg, promise);  
  24.         if (flush) {  
  25.             next.invokeFlush();  
  26.         }  
  27.     }  
  28.   
  29.     private DefaultChannelHandlerContext findContextOutbound() {  
  30.         DefaultChannelHandlerContext ctx = this;  
  31.         do {  
  32.             ctx = ctx.prev;  
  33.         } while (!ctx.outbound);  
  34.         return ctx;  
  35.     }  
  36.   
  37.     private void invokeWrite(Object msg, ChannelPromise promise) {  
  38.         try {  
  39.             ((ChannelOutboundHandler) handler).write(this, msg, promise);  
  40.         } catch (Throwable t) {  
  41.             notifyOutboundHandlerException(t, promise);  
  42.         }  
  43.     }  
  44.   
  45.     // ...  
  46. }  

context的write()方法沿著context鏈往前找,直至找到一個(gè)outbound類型的context為止,然后調(diào)用其invokeWrite()方法:


invokeWrite()接著調(diào)用handler的write()方法:

最后看看ChannelOutboundHandlerAdapter的write()方法實(shí)現(xiàn):

  1. public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {  
  2.     // ...  
  3.     @Override  
  4.     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {  
  5.         ctx.write(msg, promise);  
  6.     }  
  7.     // ...  
  8. }  

默認(rèn)的實(shí)現(xiàn)調(diào)用了context的write()方法而不做任何處理,這樣write事件就沿著outbound鏈繼續(xù)傳播:


可見,Pipeline的事件傳播,是靠Pipeline,Context和Handler共同協(xié)作完成的。


參考資料


Netty in Action

Intercepting Filter


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多