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

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

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

    linugb118--java space

    Java

    Netty Channel 接口名詞理解

     

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

    2.ChannelConfig
    channel的參數,以Map 數據結構來存儲

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

    Downstream events包括:
    write:發送信息給channel的時候 --MessageEvent
    bind:綁定一個channel到指定的本地地址 --ChannelStateEvent
    unbind:解除當前本地端口的綁定--ChannelStateEvent
    connect:將channel連接到遠程的機 --ChannelStateEvent
    disconnect:將channel與遠程的機連接斷開 --ChannelStateEvent
    close:關閉channel --ChannelStateEvent

    需要注意的是,這里沒有open event,這是因為當一個channel被channelFactory創建的話,channel總是已經被打開了。

    此外還有兩個事件類型是當父channel存在子channel的情況
    childChannelOpen:子channel被打開 ---ChannelStateEvent
    childChannelClosed:子channel被關閉 ---ChannelStateEvent

    4.ChannelHandler
    channel是負責傳送數據的載體,那么數據肯定需要根據要求進行加工處理,那么這個時候就用到ChannelHandler
    不同的加工可以構建不同的ChannelHandler,然后放入ChannelPipeline中
    此外需要有ChannelEvent觸發后才能到達ChannelHandler,因此根據event不同有下面兩種的sub接口ChannelUpstreamHandler
    和ChannelDownstreamHandler。
    一個ChannelHandler通常需要存儲一些狀態信息作為判斷信息,常用做法定義一個變量
    比如
    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>);
     *     }
     * }
     
    除了這種,每個ChannelHandler都可以從ChannelHandlerContext中獲取或設置數據,那么下面的做法就是利用ChannelHandlerContext
    設置變量
    * {@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>);
     *     }
     * }
     這兩種做法還是有區別的,上面的變量做法,每個new的handler 對象,變量是不共享的,而下面的ChannelHandlerContext是共享的
     
     如果需要不同的handler之間共享數據,那怎么辦,那就用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的集合,他參照J2ee中的Intercepting Filter模式來實現的,
    讓用戶完全掌握如果在一個handler中處理事件,同時讓pipeline里面的多個handler可以相互交互。
    Intercepting Filter:http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html
    對于每一個channel都需要有相應的channelPipeline,當為channel設置了channelPipeline后就不能再為channel重新設置
    channelPipeline。此外建議的做法的通過Channels 這個幫助類來生成ChannelPipeline 而不是自己去構建ChannelPipeline

    通常pipeLine 添加多個handler,是基于業務邏輯的
    比如下面
    {@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 執行的handler按順序應該是 125
     downstream event 執行的handler按順序應該是 543
     SimpleChannelHandler 是同時實現了 ChannelUpstreamHandler和ChannelDownstreamHandler的類
    上面只是具有邏輯,如果數據需要通過格式來進行編碼的話,那需要這些寫
     * {@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轉換為java對象
    Protocol Encoder - 將java對象轉換為binary
    ExecutionHandler - applies a thread model.
    Business Logic Handler - performs the actual business logic(e.g. database access)
    雖然不能為channel重新設置channelPipeline,但是channelPipeline本身是thread-safe,因此你可以在任何時候為channelPipeline添加刪除channelHandler

    需要注意的是,下面的代碼寫法不能達到預期的效果
     * 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);
     *     }
     * }
     前提現在Pipeline只有最后一個FirstHandler,
     上面明顯是想把FirstHandler從Pipeline中移除,然后添加SecondHandler。而pipeline需要只要有一個Handler,因此如果想到到達這個效果,那么可以
     先添加SecondHandler,然后在移除FirstHandler。

    6.ChannelFactory
    channel的工廠類,也就是用來生成channel的類,ChannelFactory根據指定的通信和網絡來生成相應的channel,比如
    NioServerSocketChannelFactory生成的channel是基于NIO server socket的。
    當一個channel創建后,ChannelPipeline將作為參數附屬給該channel。
    對于channelFactory的關閉,需要做兩步操作
    第一,關閉所有該factory產生的channel包括子channel。通常調用ChannelGroup#close()。
    第二,釋放channelFactory的資源,調用releaseExternalResources()

    7.ChannelGroup
     channel的組集合,他包含一個或多個open的channel,closed channel會自動從group中移除,一個channel可以在一個或者多個channelGroup
     如果想將一個消息廣播給多個channel,可以利用group來實現
     比如:
    {@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));

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

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

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

    11.ChannelFutureListener
    ChannelFuture監聽器,監聽channelFuture的結果。

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

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

    14.ChannelPipelineFactory
    產生ChannelPipe的工廠類

    15.ChannelState
    記載channel狀態常量

     

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


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


    網站導航:
     

    My Links

    Blog Stats

    常用鏈接

    留言簿(1)

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 99re热免费精品视频观看| 国产成人精品一区二区三区免费| 18禁美女黄网站色大片免费观看 | 精品熟女少妇aⅴ免费久久| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 久久精品免费一区二区喷潮| 久久亚洲最大成人网4438| 久久久久久免费视频| 亚洲人成激情在线播放| 韩国免费一级成人毛片| 亚洲а∨天堂久久精品9966 | 日韩免费高清视频网站| 国产成人亚洲综合无| 亚洲熟妇少妇任你躁在线观看无码| 一个人看的在线免费视频| 国产亚洲AV夜间福利香蕉149| 免费人成在线观看视频高潮| 亚洲国产精品一区第二页| 99久久精品免费精品国产| 亚洲一区二区三区播放在线| 丁香花在线观看免费观看| 国产精品亚洲专区无码不卡| 亚洲综合无码精品一区二区三区 | h在线观看视频免费网站| 久久精品国产亚洲AV蜜臀色欲| 成人免费a级毛片| 综合一区自拍亚洲综合图区| 亚洲国产专区一区| 日韩电影免费观看| 亚洲大成色www永久网址| jlzzjlzz亚洲乱熟在线播放| 久久久久国产精品免费网站| 亚洲精品第一综合99久久| 国产免费一区二区三区VR| a毛片免费播放全部完整| 亚洲成a人不卡在线观看| 免费一级成人毛片| 6080午夜一级毛片免费看 | 亚洲日本一区二区| 国产小视频免费观看| 美女视频黄的免费视频网页|