linugb118--java space

          Java

          Netty Channel 接口名詞理解

           

          1.Channel
          channel 是負(fù)責(zé)數(shù)據(jù)讀,寫的對象,有點(diǎn)類似于老的io里面的stream,他和stream的區(qū)別,channel是雙向的
          既可以write 也可以read,而stream要分outstream和inputstream。而且在NIO中用戶不應(yīng)該直接從channel中讀寫數(shù)據(jù),
          而是應(yīng)該通過buffer,通過buffer再將數(shù)據(jù)讀寫到channel中。
          一個(gè)channel 可以提供給用戶下面幾個(gè)信息
          (1)channel的當(dāng)前狀態(tài),比如open 還是closed
          (2)ChannelConfig對象,表示channel的一些參數(shù),比如bufferSize
          (3)channel支持的所有i/o操作(比如read,write,connect.bind)以及ChannelPipeLine(下面解釋)

          2.ChannelConfig
          channel的參數(shù),以Map 數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)

          3.ChannelEvent
          ChannelEvent廣義的認(rèn)為Channel相關(guān)的事件,他是否分Upstream events和downstream events兩大塊,這里需要注意的,讓是server為
          主體的話,從client的數(shù)據(jù)到server的過程是Upstream;而server到client的數(shù)據(jù)傳輸過程叫downstream;而如果以client為主體
          的話,從server到client的過程對client來說是Upstream,而client到server的過程對client來說就是downstream。
          Upstream events包括:
          messageReceived:信息被接受時(shí) ---MessageEvent
          exceptionCaught:產(chǎn)生異常時(shí) ---ExceptionEvent
          channelOpen:channel被開啟時(shí) ---ChannelStateEvent
          channelClosed:channel被關(guān)閉時(shí) ---ChannelStateEvent
          channelBound:channel被開啟并準(zhǔn)備去連接但還未連接上的時(shí)候 ---ChannelStateEvent
          channelUnbound:channel被開啟不準(zhǔn)備去連接時(shí)候 ---ChannelStateEvent
          channelConnected:channel被連接上的時(shí)候 ---ChannelStateEvent
          channelDisconnected:channel連接斷開的時(shí)候 ---ChannelStateEvent
          channelInterestChanged:Channel的interestOps被改變的時(shí)候 ------ChannelStateEvent
          writeComplete:寫到遠(yuǎn)程端完成的時(shí)候 --WriteCompletionEvent

          Downstream events包括:
          write:發(fā)送信息給channel的時(shí)候 --MessageEvent
          bind:綁定一個(gè)channel到指定的本地地址 --ChannelStateEvent
          unbind:解除當(dāng)前本地端口的綁定--ChannelStateEvent
          connect:將channel連接到遠(yuǎn)程的機(jī) --ChannelStateEvent
          disconnect:將channel與遠(yuǎn)程的機(jī)連接斷開 --ChannelStateEvent
          close:關(guān)閉channel --ChannelStateEvent

          需要注意的是,這里沒有open event,這是因?yàn)楫?dāng)一個(gè)channel被channelFactory創(chuàng)建的話,channel總是已經(jīng)被打開了。

          此外還有兩個(gè)事件類型是當(dāng)父channel存在子channel的情況
          childChannelOpen:子channel被打開 ---ChannelStateEvent
          childChannelClosed:子channel被關(guān)閉 ---ChannelStateEvent

          4.ChannelHandler
          channel是負(fù)責(zé)傳送數(shù)據(jù)的載體,那么數(shù)據(jù)肯定需要根據(jù)要求進(jìn)行加工處理,那么這個(gè)時(shí)候就用到ChannelHandler
          不同的加工可以構(gòu)建不同的ChannelHandler,然后放入ChannelPipeline中
          此外需要有ChannelEvent觸發(fā)后才能到達(dá)ChannelHandler,因此根據(jù)event不同有下面兩種的sub接口ChannelUpstreamHandler
          和ChannelDownstreamHandler。
          一個(gè)ChannelHandler通常需要存儲(chǔ)一些狀態(tài)信息作為判斷信息,常用做法定義一個(gè)變量
          比如
          public class DataServerHandler extends {@link SimpleChannelHandler} {
           *
           *     <b>private boolean loggedIn;</b>
           *
           *     {@code @Override}
           *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
           *         {@link Channel} ch = e.getChannel();
           *         Object o = e.getMessage();
           *         if (o instanceof LoginMessage) {
           *             authenticate((LoginMessage) o);
           *             <b>loggedIn = true;</b>
           *         } else (o instanceof GetDataMessage) {
           *             if (<b>loggedIn</b>) {
           *                 ch.write(fetchSecret((GetDataMessage) o));
           *             } else {
           *                 fail();
           *             }
           *         }
           *     }
           *     ...
           * }
           
           // Create a new handler instance per channel.
           * // See {@link Bootstrap#setPipelineFactory(ChannelPipelineFactory)}.
           * public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
           *     public {@link ChannelPipeline} getPipeline() {
           *         return {@link Channels}.pipeline(<b>new DataServerHandler()</b>);
           *     }
           * }
           
          除了這種,每個(gè)ChannelHandler都可以從ChannelHandlerContext中獲取或設(shè)置數(shù)據(jù),那么下面的做法就是利用ChannelHandlerContext
          設(shè)置變量
          * {@code @Sharable}
           * public class DataServerHandler extends {@link SimpleChannelHandler} {
           *
           *     {@code @Override}
           *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
           *         {@link Channel} ch = e.getChannel();
           *         Object o = e.getMessage();
           *         if (o instanceof LoginMessage) {
           *             authenticate((LoginMessage) o);
           *             <b>ctx.setAttachment(true)</b>;
           *         } else (o instanceof GetDataMessage) {
           *             if (<b>Boolean.TRUE.equals(ctx.getAttachment())</b>) {
           *                 ch.write(fetchSecret((GetDataMessage) o));
           *             } else {
           *                 fail();
           *             }
           *         }
           *     }
           *     ...
           * }
           
           * public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
           *
           *     private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
           *
           *     public {@link ChannelPipeline} getPipeline() {
           *         return {@link Channels}.pipeline(<b>SHARED</b>);
           *     }
           * }
           這兩種做法還是有區(qū)別的,上面的變量做法,每個(gè)new的handler 對象,變量是不共享的,而下面的ChannelHandlerContext是共享的
           
           如果需要不同的handler之間共享數(shù)據(jù),那怎么辦,那就用ChannelLocal
           例子:
            public final class DataServerState {
           *
           *     <b>public static final {@link ChannelLocal}&lt;Boolean&gt; loggedIn = new {@link ChannelLocal}&lt;Boolean&gt;() {
           *         protected Boolean initialValue(Channel channel) {
           *             return false;
           *         }
           *     }</b>
           *     ...
           * }
           *
           * {@code @Sharable}
           * public class DataServerHandler extends {@link SimpleChannelHandler} {
           *
           *     {@code @Override}
           *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
           *         Channel ch = e.getChannel();
           *         Object o = e.getMessage();
           *         if (o instanceof LoginMessage) {
           *             authenticate((LoginMessage) o);
           *             <b>DataServerState.loggedIn.set(ch, true);</b>
           *         } else (o instanceof GetDataMessage) {
           *             if (<b>DataServerState.loggedIn.get(ch)</b>) {
           *                 ctx.getChannel().write(fetchSecret((GetDataMessage) o));
           *             } else {
           *                 fail();
           *             }
           *         }
           *     }
           *     ...
           * }
           *
           * // Print the remote addresses of the authenticated clients:
           * {@link ChannelGroup} allClientChannels = ...;
           * for ({@link Channel} ch: allClientChannels) {
           *     if (<b>DataServerState.loggedIn.get(ch)</b>) {
           *         System.out.println(ch.getRemoteAddress());
           *     }
           * }
           * </pre>
           
          5.ChannelPipeline
          channelPipeline是一系列channelHandler的集合,他參照J(rèn)2ee中的Intercepting Filter模式來實(shí)現(xiàn)的,
          讓用戶完全掌握如果在一個(gè)handler中處理事件,同時(shí)讓pipeline里面的多個(gè)handler可以相互交互。
          Intercepting Filter:http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html
          對于每一個(gè)channel都需要有相應(yīng)的channelPipeline,當(dāng)為channel設(shè)置了channelPipeline后就不能再為channel重新設(shè)置
          channelPipeline。此外建議的做法的通過Channels 這個(gè)幫助類來生成ChannelPipeline 而不是自己去構(gòu)建ChannelPipeline

          通常pipeLine 添加多個(gè)handler,是基于業(yè)務(wù)邏輯的
          比如下面
          {@link ChannelPipeline} p = {@link Channels}.pipeline();
           * p.addLast("1", new UpstreamHandlerA());
           * p.addLast("2", new UpstreamHandlerB());
           * p.addLast("3", new DownstreamHandlerA());
           * p.addLast("4", new DownstreamHandlerB());
           * p.addLast("5", new SimpleChannelHandler());
           upstream event 執(zhí)行的handler按順序應(yīng)該是 125
           downstream event 執(zhí)行的handler按順序應(yīng)該是 543
           SimpleChannelHandler 是同時(shí)實(shí)現(xiàn)了 ChannelUpstreamHandler和ChannelDownstreamHandler的類
          上面只是具有邏輯,如果數(shù)據(jù)需要通過格式來進(jìn)行編碼的話,那需要這些寫
           * {@link ChannelPipeline} pipeline = {@link Channels#pipeline() Channels.pipeline()};
           * pipeline.addLast("decoder", new MyProtocolDecoder());
           * pipeline.addLast("encoder", new MyProtocolEncoder());
           * pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
           * pipeline.addLast("handler", new MyBusinessLogicHandler());
           其中:
          Protocol Decoder - 將binary轉(zhuǎn)換為java對象
          Protocol Encoder - 將java對象轉(zhuǎn)換為binary
          ExecutionHandler - applies a thread model.
          Business Logic Handler - performs the actual business logic(e.g. database access)
          雖然不能為channel重新設(shè)置channelPipeline,但是channelPipeline本身是thread-safe,因此你可以在任何時(shí)候?yàn)閏hannelPipeline添加刪除channelHandler

          需要注意的是,下面的代碼寫法不能達(dá)到預(yù)期的效果
           * public class FirstHandler extends {@link SimpleChannelUpstreamHandler} {
           *
           *     {@code @Override}
           *     public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
           *         // Remove this handler from the pipeline,
           *         ctx.getPipeline().remove(this);
           *         // And let SecondHandler handle the current event.
           *         ctx.getPipeline().addLast("2nd", new SecondHandler());
           *         ctx.sendUpstream(e);
           *     }
           * }
           前提現(xiàn)在Pipeline只有最后一個(gè)FirstHandler,
           上面明顯是想把FirstHandler從Pipeline中移除,然后添加SecondHandler。而pipeline需要只要有一個(gè)Handler,因此如果想到到達(dá)這個(gè)效果,那么可以
           先添加SecondHandler,然后在移除FirstHandler。

          6.ChannelFactory
          channel的工廠類,也就是用來生成channel的類,ChannelFactory根據(jù)指定的通信和網(wǎng)絡(luò)來生成相應(yīng)的channel,比如
          NioServerSocketChannelFactory生成的channel是基于NIO server socket的。
          當(dāng)一個(gè)channel創(chuàng)建后,ChannelPipeline將作為參數(shù)附屬給該channel。
          對于channelFactory的關(guān)閉,需要做兩步操作
          第一,關(guān)閉所有該factory產(chǎn)生的channel包括子channel。通常調(diào)用ChannelGroup#close()。
          第二,釋放channelFactory的資源,調(diào)用releaseExternalResources()

          7.ChannelGroup
           channel的組集合,他包含一個(gè)或多個(gè)open的channel,closed channel會(huì)自動(dòng)從group中移除,一個(gè)channel可以在一個(gè)或者多個(gè)channelGroup
           如果想將一個(gè)消息廣播給多個(gè)channel,可以利用group來實(shí)現(xiàn)
           比如:
          {@link ChannelGroup} recipients = new {@link DefaultChannelGroup}()
          recipients.add(channelA);
          recipients.add(channelB);
          recipients.write(ChannelBuffers.copiedBuffer("Service will shut down for maintenance in 5 minutes.",CharsetUtil.UTF_8));

          當(dāng)ServerChannel和非ServerChannel同時(shí)都在channelGroup中的時(shí)候,任何io請求的操作都是先在ServerChannel中執(zhí)行再在其他Channel中執(zhí)行。
          這個(gè)規(guī)則對關(guān)閉一個(gè)server非常適用。
           
          8.ChannelFuture
          在netty中,所有的io傳輸都是異步,所有那么在傳送的時(shí)候需要數(shù)據(jù)+狀態(tài)來確定是否全部傳送成功,而這個(gè)載體就是ChannelFuture。

          9.ChannelGroupFuture
          針對一次ChannelGroup異步操作的結(jié)果,他和ChannelFuture一樣,包括數(shù)據(jù)和狀態(tài)。不同的是他由channelGroup里面channel的所有channelFuture
          組成。

          10.ChannelGroupFutureListener
          針對ChannelGroupFuture的監(jiān)聽器,同樣建議使用ChannelGroupFutureListener而不是await();

          11.ChannelFutureListener
          ChannelFuture監(jiān)聽器,監(jiān)聽channelFuture的結(jié)果。

          12.ChannelFutureProgressListener
          監(jiān)聽ChannelFuture處理過程,比如一個(gè)大文件的傳送。而ChannelFutureListener只監(jiān)聽ChannelFuture完成未完成

          13.ChannelHandlerContext
          如何讓handler和他的pipeLine以及pipeLine中的其他handler交換,那么就要用到ChannelHandlerContext,
          ChannelHandler可以通過ChannelHandlerContext的sendXXXstream(ChannelEvent)將event傳給最近的handler
          可以通過ChannelHandlerContext的getPipeline來得到Pipeline,并修改他,ChannelHandlerContext還可以存放一下狀態(tài)信息attments。
          一個(gè)ChannelHandler實(shí)例可以有一個(gè)或者多個(gè)ChannelHandlerContext

          14.ChannelPipelineFactory
          產(chǎn)生ChannelPipe的工廠類

          15.ChannelState
          記載channel狀態(tài)常量

           

          posted on 2010-11-12 15:36 linugb118 閱讀(3782) 評論(0)  編輯  收藏


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


          網(wǎng)站導(dǎo)航:
           

          My Links

          Blog Stats

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 兴宁市| 定兴县| 肥城市| 建始县| 和林格尔县| 太湖县| 西平县| 栾川县| 余江县| 广宁县| 平和县| 喀喇沁旗| 丹凤县| 平顶山市| 克东县| 崇信县| 蒙阴县| 福贡县| 胶州市| 南岸区| 吉木萨尔县| 云浮市| 克拉玛依市| 监利县| 镇坪县| 家居| 缙云县| 仁寿县| 宁陕县| 临潭县| 林西县| 佛山市| 泾川县| 佛坪县| 罗甸县| 夏邑县| 德化县| 环江| 山阳县| 利川市| 东辽县|