国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

Netty接口ChannelHandlerContext

2018-08-08 10:38 更新

在ChannelHandler 添加到 ChannelPipeline 時(shí)會(huì)創(chuàng)建一個(gè)實(shí)例,就是接口 ChannelHandlerContext,它代表了 ChannelHandler 和ChannelPipeline 之間的關(guān)聯(lián)。接口ChannelHandlerContext 主要是對(duì)通過(guò)同一個(gè) ChannelPipeline 關(guān)聯(lián)的 ChannelHandler 之間的交互進(jìn)行管理

ChannelHandlerContext 中包含了有許多方法,其中一些方法也出現(xiàn)在 Channel 和ChannelPipeline 本身。如果您通過(guò)Channel 或ChannelPipeline 的實(shí)例來(lái)調(diào)用這些方法,他們就會(huì)在整個(gè) pipeline中傳播 。相比之下,一樣的方法在 ChannelHandlerContext 的實(shí)例上調(diào)用, 就只會(huì)從當(dāng)前的 ChannelHandler 開(kāi)始并傳播到相關(guān)管道中的下一個(gè)有處理事件能力的 ChannelHandler 。

ChannelHandlerContext API 總結(jié)如下:

Table 6.10 ChannelHandlerContext API

名稱描述
bindRequest to bind to the given SocketAddress and return a ChannelFuture.
channelReturn the Channel which is bound to this instance.
closeRequest to close the Channel and return a ChannelFuture.
connectRequest to connect to the given SocketAddress and return a ChannelFuture.
deregisterRequest to deregister from the previously assigned EventExecutor and return a ChannelFuture.
disconnectRequest to disconnect from the remote peer and return a ChannelFuture.
executorReturn the EventExecutor that dispatches events.
fireChannelActiveA Channel is active (connected).
fireChannelInactiveA Channel is inactive (closed).
fireChannelReadA Channel received a message.
fireChannelReadCompleteTriggers a channelWritabilityChanged event to the next

ChannelInboundHandler. handler | Returns the ChannelHandler bound to this instance. isRemoved | Returns true if the associated ChannelHandler was removed from the ChannelPipeline. name | Returns the unique name of this instance. pipeline | Returns the associated ChannelPipeline. read | Request to read data from the Channel into the first inbound buffer. Triggers a channelRead event if successful and notifies the handler of channelReadComplete. write | Request to write a message via this instance through the pipeline.

其他注意注意事項(xiàng):

  • ChannelHandlerContext 與 ChannelHandler 的關(guān)聯(lián)從不改變,所以緩存它的引用是安全的。
  • 正如我們前面指出的,ChannelHandlerContext 所包含的事件流比其他類(lèi)中同樣的方法都要短,利用這一點(diǎn)可以盡可能高地提高性能。

使用 ChannelHandler

本節(jié),我們將說(shuō)明 ChannelHandlerContext的用法 ,以及ChannelHandlerContext, Channel 和 ChannelPipeline 這些類(lèi)中方法的不同表現(xiàn)。下圖展示了 ChannelPipeline, Channel, ChannelHandler 和 ChannelHandlerContext 的關(guān)系

Figure%206

  1. Channel 綁定到 ChannelPipeline
  2. ChannelPipeline 綁定到 包含 ChannelHandler 的 Channel
  3. ChannelHandler
  4. 當(dāng)添加 ChannelHandler 到 ChannelPipeline 時(shí),ChannelHandlerContext 被創(chuàng)建

Figure 6.3 Channel, ChannelPipeline, ChannelHandler and ChannelHandlerContext

下面展示了, 從 ChannelHandlerContext 獲取到 Channel 的引用,通過(guò)調(diào)用 Channel 上的 write() 方法來(lái)觸發(fā)一個(gè) 寫(xiě)事件到通過(guò)管道的的流中

Listing 6.6 Accessing the Channel from a ChannelHandlerContext

ChannelHandlerContext ctx = context;
Channel channel = ctx.channel();  //1
channel.write(Unpooled.copiedBuffer("Netty in Action",
        CharsetUtil.UTF_8));  //2
  1. 得到與 ChannelHandlerContext 關(guān)聯(lián)的 Channel 的引用
  2. 通過(guò) Channel 寫(xiě)緩存

下面展示了 從 ChannelHandlerContext 獲取到 ChannelPipeline 的相同示例

Listing 6.7 Accessing the ChannelPipeline from a ChannelHandlerContext

ChannelHandlerContext ctx = context;
ChannelPipeline pipeline = ctx.pipeline(); //1
pipeline.write(Unpooled.copiedBuffer("Netty in Action", CharsetUtil.UTF_8));  //2
  1. 得到與 ChannelHandlerContext 關(guān)聯(lián)的 ChannelPipeline 的引用
  2. 通過(guò) ChannelPipeline 寫(xiě)緩沖區(qū)

流在兩個(gè)清單6.6和6.7是一樣的,如圖6.4所示。重要的是要注意,雖然在 Channel 或者 ChannelPipeline 上調(diào)用write() 都會(huì)把事件在整個(gè)管道傳播,但是在 ChannelHandler 級(jí)別上,從一個(gè)處理程序轉(zhuǎn)到下一個(gè)卻要通過(guò)在 ChannelHandlerContext 調(diào)用方法實(shí)現(xiàn)。

Figure%206

  1. 事件傳遞給 ChannelPipeline 的第一個(gè) ChannelHandler
  2. ChannelHandler 通過(guò)關(guān)聯(lián)的 ChannelHandlerContext 傳遞事件給 ChannelPipeline 中的 下一個(gè)
  3. ChannelHandler 通過(guò)關(guān)聯(lián)的 ChannelHandlerContext 傳遞事件給 ChannelPipeline 中的 下一個(gè)

Figure 6.4 Event propagation via the Channel or the ChannelPipeline

為什么你可能會(huì)想從 ChannelPipeline 一個(gè)特定的點(diǎn)開(kāi)始傳播一個(gè)事件?

  • 通過(guò)減少 ChannelHandler 不感興趣的事件的傳遞,從而減少開(kāi)銷(xiāo)
  • 排除掉特定的對(duì)此事件感興趣的處理程序的處理

想要實(shí)現(xiàn)從一個(gè)特定的 ChannelHandler 開(kāi)始處理,你必須引用與 此ChannelHandler的前一個(gè)ChannelHandler 關(guān)聯(lián)的 ChannelHandlerContext 。這個(gè)ChannelHandlerContext 將會(huì)調(diào)用與自身關(guān)聯(lián)的 ChannelHandler 的下一個(gè)ChannelHandler 。

下面展示了使用場(chǎng)景

Listing 6.8 Events via ChannelPipeline

ChannelHandlerContext ctx = context;
ctx.write(Unpooled.copiedBuffer("Netty in Action",              CharsetUtil.UTF_8));
  1. 獲得 ChannelHandlerContext 的引用
  2. write() 將會(huì)把緩沖區(qū)發(fā)送到下一個(gè) ChannelHandler

如下所示,消息將會(huì)從下一個(gè)ChannelHandler開(kāi)始流過(guò) ChannelPipeline ,繞過(guò)所有在它之前的ChannelHandler。

Figure%206

  1. ChannelHandlerContext 方法調(diào)用
  2. 事件發(fā)送到了下一個(gè) ChannelHandler
  3. 經(jīng)過(guò)最后一個(gè)ChannelHandler后,事件從 ChannelPipeline 移除

Figure 6.5 Event flow for operations triggered via the ChannelHandlerContext

我們剛剛描述的用例是一種常見(jiàn)的情形,當(dāng)我們想要調(diào)用某個(gè)特定的 ChannelHandler操作時(shí),它尤其有用。

ChannelHandler 和 ChannelHandlerContext 的高級(jí)用法

正如我們?cè)谇鍐?.6中看到的,通過(guò)調(diào)用ChannelHandlerContext的 pipeline() 方法,你可以得到一個(gè)封閉的 ChannelPipeline 引用。這使得可以在運(yùn)行時(shí)操作 pipeline 的 ChannelHandler ,這一點(diǎn)可以被利用來(lái)實(shí)現(xiàn)一些復(fù)雜的需求,例如,添加一個(gè) ChannelHandler 到 pipeline 來(lái)支持動(dòng)態(tài)協(xié)議改變。

其他高級(jí)用例可以實(shí)現(xiàn)通過(guò)保持一個(gè) ChannelHandlerContext 引用供以后使用,這可能發(fā)生在任何 ChannelHandler 方法,甚至來(lái)自不同的線程。清單6.9顯示了此模式被用來(lái)觸發(fā)一個(gè)事件。

Listing 6.9 ChannelHandlerContext usage

public class WriteHandler extends ChannelHandlerAdapter {

    private ChannelHandlerContext ctx;

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        this.ctx = ctx;        //1
    }

    public void send(String msg) {
        ctx.writeAndFlush(msg);  //2
    }
}
  1. 存儲(chǔ) ChannelHandlerContext 的引用供以后使用
  2. 使用之前存儲(chǔ)的 ChannelHandlerContext 來(lái)發(fā)送消息

因?yàn)?ChannelHandler 可以屬于多個(gè) ChannelPipeline ,它可以綁定多個(gè) ChannelHandlerContext 實(shí)例。然而,ChannelHandler 用于這種用法必須添加 @Sharable 注解。否則,試圖將它添加到多個(gè) ChannelPipeline 將引發(fā)一個(gè)異常。此外,它必須既是線程安全的又能安全地使用多個(gè)同時(shí)的通道(比如,連接)。

清單6.10顯示了此模式的正確實(shí)現(xiàn)。

Listing 6.10 A shareable ChannelHandler

@ChannelHandler.Sharable            //1
public class SharableHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println("channel read message " + msg);
        ctx.fireChannelRead(msg);  //2
    }
}
  1. 添加 @Sharable 注解
  2. 日志方法調(diào)用, 并專(zhuān)遞到下一個(gè) ChannelHandler

上面這個(gè) ChannelHandler 實(shí)現(xiàn)符合所有包含在多個(gè)管道的要求;它通過(guò)@Sharable 注解,并不持有任何狀態(tài)。而下面清單6.11中列出的情況則恰恰相反,它會(huì)造成問(wèn)題。

Listing 6.11 Invalid usage of @Sharable

@ChannelHandler.Sharable  //1
public class NotSharableHandler extends ChannelInboundHandlerAdapter {
    private int count;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        count++;  //2

        System.out.println("inboundBufferUpdated(...) called the "
        + count + " time");  //3
        ctx.fireChannelRead(msg);
    }

}
  1. 添加 @Sharable
  2. count 字段遞增
  3. 日志方法調(diào)用, 并專(zhuān)遞到下一個(gè) ChannelHandler

這段代碼的問(wèn)題是它持有狀態(tài):一個(gè)實(shí)例變量保持了方法調(diào)用的計(jì)數(shù)。將這個(gè)類(lèi)的一個(gè)實(shí)例添加到 ChannelPipeline 并發(fā)訪問(wèn)通道時(shí)很可能產(chǎn)生錯(cuò)誤。(當(dāng)然,這個(gè)簡(jiǎn)單的例子中可以通過(guò)在 channelRead() 上添加 synchronized 來(lái)糾正 )

總之,使用@Sharable的話,要確定 ChannelHandler 是線程安全的。

為什么共享 ChannelHandler

常見(jiàn)原因是要在多個(gè) ChannelPipelines 上安裝一個(gè) ChannelHandler 以此來(lái)實(shí)現(xiàn)跨多個(gè)渠道收集統(tǒng)計(jì)數(shù)據(jù)的目的。

我們的討論 ChannelHandlerContext 及與其他框架組件關(guān)系的 到此結(jié)束。接下來(lái)我們將解析 Channel 狀態(tài)模型,準(zhǔn)備仔細(xì)看看ChannelHandler 本身。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)