<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    瘋狂

    STANDING ON THE SHOULDERS OF GIANTS
    posts - 481, comments - 486, trackbacks - 0, articles - 1
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Netty 概述(轉)

    Posted on 2016-07-13 09:49 瘋狂 閱讀(977) 評論(0)  編輯  收藏 所屬分類: netty
    轉載自http://blog.csdn.net/zxhoo/article/details/17264263

    Netty4

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

    Channel


    Channel是Netty最核心的接口,一個Channel就是一個聯絡Socket的通道,通過Channel,你可以對Socket進行各種操作。

    ChannelHandler

    用Netty編寫網絡程序的時候,你很少直接操縱Channel,而是通過ChannelHandler來間接操縱Channel。

    Netty中的所有handler都實現自ChannelHandler接口。按照輸出輸出來分,分為ChannelInboundHandler、ChannelOutboundHandler兩大類

    ChannelInboundHandler對從客戶端發往服務器的報文進行處理,一般用來執行解碼、讀取客戶端數據、進行業務處理等;

    ChannelOutboundHandler對從服務器發往客戶端的報文進行處理,一般用來進行編碼、發送報文到客戶端。

    ChannelPipeline

    ChannelPipeline實際上應該叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一個ChandlerHandler的鏈表,當需要對Channel進行某種處理的時候,Pipeline負責依次調用每一個Handler進行處理。每個Channel都有一個屬于自己的Pipeline,調用Channel#pipeline()方法可以獲得Channel的Pipeline,調用Pipeline#channel()方法可以獲得Pipeline的Channel。

    netty概述

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

    ChannelPipeline addFirst(String name, ChannelHandler handler); ChannelPipeline addLast(String name, ChannelHandler handler); ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler); ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler); ChannelPipeline remove(ChannelHandler handler); ChannelHandler remove(String name); ChannelHandler removeFirst(); ChannelHandler removeLast(); ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler); ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler); ChannelHandler first(); ChannelHandler last(); ChannelHandler get(String name);

    ChannelHandlerContext

    ChannelPipeline并不是直接管理ChannelHandler,而是通過ChannelHandlerContext來間接管理,這一點通過ChannelPipeline的默認實現DefaultChannelPipeline可以看出來。

    netty概述

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

    ChannelPipeline和ChannelHandlerContext默認實現

    DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默認實現,下面是它們的部分代碼:

    final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {      volatile DefaultChannelHandlerContext next;     volatile DefaultChannelHandlerContext prev;      private final boolean inbound;     private final boolean outbound;     private final AbstractChannel channel;     private final DefaultChannelPipeline pipeline;     private final String name;     private final ChannelHandler handler;     private boolean removed;      // ... }

    final class DefaultChannelPipeline implements ChannelPipeline {     // ...      final DefaultChannelHandlerContext head;     final DefaultChannelHandlerContext tail;      // ... }

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

    netty概述

    再來看看DefaultChannelPipeline的構造函數:

        public DefaultChannelPipeline(AbstractChannel channel) {         if (channel == null) {             throw new NullPointerException("channel");         }         this.channel = channel;          TailHandler tailHandler = new TailHandler();         tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);          HeadHandler headHandler = new HeadHandler(channel.unsafe());         head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);          head.next = tail;         tail.prev = head;     }

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

    netty概述

    ChannelHandler的種類

    Netty中的所有handler都實現自ChannelHandler接口。按照輸出輸出來分,分為ChannelInboundHandler、ChannelOutboundHandler兩大類。ChannelInboundHandler對從客戶端發往服務器的報文進行處理,一般用來執行解碼、讀取客戶端數據、進行業務處理等;ChannelOutboundHandler對從服務器發往客戶端的報文進行處理,一般用來進行編碼、發送報文到客戶端。

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

    public interface ChannelInboundHandler extends ChannelHandler {   // ... }  public interface ChannelOutboundHandler extends ChannelHandler {   // ... }


    事件的傳播

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

    public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {     // ...     @Override     public Channel write(Object msg) {         return pipeline.write(msg);     }     // ... }

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

    netty概述

    final class DefaultChannelPipeline implements ChannelPipeline {     // ...     @Override     public ChannelFuture write(Object msg) {         return tail.write(msg);     }     // ... }

    因為write是個outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,調用其write()方法:

    netty概述

    接著看DefaultChannelHandlerContext的write()方法:

    final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {     // ...     @Override     public ChannelFuture write(Object msg) {         return write(msg, newPromise());     }      @Override     public ChannelFuture write(final Object msg, final ChannelPromise promise) {         if (msg == null) {             throw new NullPointerException("msg");         }          validatePromise(promise, true);          write(msg, false, promise);          return promise;     }      private void write(Object msg, boolean flush, ChannelPromise promise) {         DefaultChannelHandlerContext next = findContextOutbound();         next.invokeWrite(msg, promise);         if (flush) {             next.invokeFlush();         }     }      private DefaultChannelHandlerContext findContextOutbound() {         DefaultChannelHandlerContext ctx = this;         do {             ctx = ctx.prev;         } while (!ctx.outbound);         return ctx;     }      private void invokeWrite(Object msg, ChannelPromise promise) {         try {             ((ChannelOutboundHandler) handler).write(this, msg, promise);         } catch (Throwable t) {             notifyOutboundHandlerException(t, promise);         }     }      // ... }

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

    netty概述

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

    netty概述

    最后看看ChannelOutboundHandlerAdapter的write()方法實現:

    public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {     // ...     @Override     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {         ctx.write(msg, promise);     }     // ... }

    默認的實現調用了context的write()方法而不做任何處理,這樣write事件就沿著outbound鏈繼續傳播:

    netty概述

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


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲人成网77777色在线播放| 亚洲国产精品综合久久网络| 久久亚洲精品国产精品| 中国性猛交xxxxx免费看| 亚洲乱亚洲乱妇无码麻豆| 福利免费在线观看| 亚洲av永久无码精品网站| 一个人免费视频观看在线www | 精品剧情v国产在免费线观看| 中文字幕在线观看亚洲视频| 最近免费中文字幕4| 亚洲国产欧美一区二区三区| 国产又大又粗又硬又长免费| 高潮毛片无遮挡高清免费视频| 国产免费爽爽视频免费可以看| 视频一区在线免费观看| 亚洲AV中文无码乱人伦在线视色| 国产福利免费视频| 亚洲电影中文字幕| 国产在线观看片a免费观看| 亚洲AⅤ男人的天堂在线观看| 亚洲国产精品无码久久青草 | 噼里啪啦电影在线观看免费高清| 亚洲人成无码网站在线观看| 国产无遮挡吃胸膜奶免费看| 亚洲免费无码在线| 久久亚洲私人国产精品vA| 巨胸喷奶水视频www网免费| 一区二区三区AV高清免费波多| 亚洲VA中文字幕无码毛片 | 亚洲AV无码一区二区大桥未久| 亚洲国产精品毛片av不卡在线 | 中文字幕无线码免费人妻| 亚洲国产精品第一区二区| 无码国产精品久久一区免费| 美女扒开尿口给男人爽免费视频 | www成人免费视频| 亚洲小说图片视频| 亚洲国产成人精品女人久久久 | 大学生a级毛片免费观看 | 亚洲国产电影在线观看|