瘋狂

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

          Netty 概述(轉(zhuǎn))

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

          Netty4

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

          Channel


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

          ChannelHandler

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

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

          ChannelInboundHandler對從客戶端發(fā)往服務(wù)器的報(bào)文進(jìn)行處理,一般用來執(zhí)行解碼、讀取客戶端數(shù)據(jù)、進(jìn)行業(yè)務(wù)處理等;

          ChannelOutboundHandler對從服務(wù)器發(fā)往客戶端的報(bào)文進(jìn)行處理,一般用來進(jìn)行編碼、發(fā)送報(bào)文到客戶端。

          ChannelPipeline

          ChannelPipeline實(shí)際上應(yīng)該叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一個(gè)ChandlerHandler的鏈表,當(dāng)需要對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。

          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來間接管理,這一點(diǎn)通過ChannelPipeline的默認(rèn)實(shí)現(xiàn)DefaultChannelPipeline可以看出來。

          netty概述

          調(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),下面是它們的部分代碼:

          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內(nèi)部,DefaultChannelHandlerContext組成了一個(gè)雙向鏈表:

          netty概述

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

              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內(nèi)部使用了兩個(gè)特殊的Handler來表示Handler鏈的頭和尾:

          netty概述

          ChannelHandler的種類

          Netty中的所有handler都實(shí)現(xiàn)自ChannelHandler接口。按照輸出輸出來分,分為ChannelInboundHandler、ChannelOutboundHandler兩大類。ChannelInboundHandler對從客戶端發(fā)往服務(wù)器的報(bào)文進(jìn)行處理,一般用來執(zhí)行解碼、讀取客戶端數(shù)據(jù)、進(jìn)行業(yè)務(wù)處理等;ChannelOutboundHandler對從服務(wù)器發(fā)往客戶端的報(bào)文進(jìn)行處理,一般用來進(jìn)行編碼、發(fā)送報(bào)文到客戶端。

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

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


          事件的傳播

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

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

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

          netty概述

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

          因?yàn)閣rite是個(gè)outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,調(diào)用其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鏈往前找,直至找到一個(gè)outbound類型的context為止,然后調(diào)用其invokeWrite()方法:

          netty概述

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

          netty概述

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

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

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

          netty概述

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


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 湟源县| 灵川县| 根河市| 乌兰县| 儋州市| 景德镇市| 黔南| 大城县| 兰溪市| 瑞昌市| 万州区| 南开区| 张北县| 法库县| 海林市| 和林格尔县| 南漳县| 龙口市| 丹阳市| 垦利县| 额尔古纳市| 昌黎县| 开江县| 韶关市| 麻江县| 宁国市| 石林| 临武县| 昌邑市| 保亭| 象州县| 东港市| 平江县| 澜沧| 永福县| 永德县| 正定县| 黄浦区| 罗山县| 凤山县| 清新县|