看看文档,它说:
https://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html
假设用户在管道中有一个或多个ChannelHandlers来接收I/O事件(例如读取)和请求I/O操作(例如写入和关闭)。例如,一个典型的服务器在每个通道的管道中都有以下处理程序,但是根据协议和业务逻辑的复杂性和特征,这些处理程序可能会有所不同:
协议解码器-将二进制数据(如ByteBuf)翻译成Java对象。协议编码器——将Java对象翻译成二进制数据。
业务逻辑处理程序 - 执行实际的业务逻辑(例如数据库访问)。它可以表示如下例所示:静态最终事件演示组 = 新的默认事件演示组(16);...
通道管道 = 通道管道();
pipeline.addLast("decoder ",new MyProtocolDecoder());
pipeline.addLast(“encoder”, new MyProtocolEncoder());
告诉管道在与 I/O 线程不同的线程中运行 MyBusinessLogicHandler 的事件处理程序方法 //,以便 I/O 线程不会被耗时的任务阻塞 。如果业务逻辑是完全异步的或完成速度非常快,则无需 // 指定组。
pipeline.addLast(group,"handler", new MyBusinessLogicHandler());
在Github上的很多例子中,我看到了同样的模式。我想知道是否有人可以解释为什么商业Handler不在解码器和编码器之间。我认为你会得到你的POJO,然后在业务处理程序中处理它,然后对其进行编码。
事实上,如果您在服务器中添加1.decoder、2.businessHandler和3.encoder,并编写ctx.channel()。writeAndFlush()
或ctx.pipeline()。writeAndFlush()
,然后将调用编码器。在这种情况下是bc,它将从尾部查找前一个outboundChannel。但是,如果您编写了ctx。writeAndFlush()
,它将从businessHandler的位置查找前一个outboundChannel。在AbstractChannelHandlerContext的findContextOutbound()
的第一行添加一个断点,您就会得到它。
java prettyprint-override">private AbstractChannelHandlerContext findContextOutbound(int mask) {
AbstractChannelHandlerContext ctx = this;
EventExecutor currentExecutor = executor();
do {
ctx = ctx.prev;
} while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));
return ctx;
}
当然,业务处理程序位于解码器和编码器之间。以阶乘为例。
public void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
if (sslCtx != null) {
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
}
// Enable stream compression (you can remove these two if unnecessary)
pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
// Add the number codec first,
pipeline.addLast(new BigIntegerDecoder());
pipeline.addLast(new NumberEncoder());
// and then business logic.
// Please note we create a handler for every new channel
// because it has stateful properties.
pipeline.addLast(new FactorialServerHandler());
}`
思想在initChannel
的函数中,流水线首先添加编码器和解码器,最后添加处理程序。执行流程实际上是按解码器、处理程序和编码器排序的。解码器、处理程序和编码器等处理程序实际上存储在AbstractChannelHandlerContext
类中。Netty中有一个AbstractChannelHandlerContext
的链表。该列表的排列方式类似于解码器上下文
--
解码器和编码器通常位于管道的开头,因为调用处理程序的顺序。对于传入的数据,它是自下而上的,对于传出的数据,它是自上而下的。
例如。
pipeline.addLast(new MyEncoder());
pipeline.addLast(new MyDecoder());
pipeline.addLast(new MyBusiness());
在这种情况下,对于传入数据调用顺序为:我的解码器(将数据转换为POJO)-
如果您在业务处理程序(实际上是解码器之后的POJOs)中接收到一个传入的流,并对其进行处理和写回,看起来好像MyBusiness位于编码器和解码器之间,因为数据返回到编码器。
我最近开始用netty做我的一个项目。为了理解netty是如何工作的,我实现了HexDumpProxy示例。当我在通道管道中添加StringDecoder和StringEncoder时,我遇到了一个问题,这会导致管道损坏。如果解码器/编码器不存在,程序会正常工作。有人能解释一下为什么会这样吗?非常感谢任何帮助! 下面我正在添加代码。 主要类别: 初始值设定项类: 前端处理程序类: 后端处理程序类:
Netty 的是一个复杂和先进的框架,但它并不玄幻。当我们请求一些设置了 key 的给定值时,我们知道 Request 类的一个实例被创建来代表这个请求。但 Netty 并不知道 Request 对象是如何转成 Memcached 所期望的。Memcached 所期望的是字节序列;忽略使用的协议,数据在网络上传输永远是字节序列。 将 Request 对象转为 Memcached 所需的字节序列,N
我用Netty制作了一个服务器,但我遇到了一个问题。我创建的编码器没有被执行。 我在服务器上的管道: 我的编码器: 我的解码器: 我的通道处理程序: 调用解码器,然后调用通道处理程序,但不调用编码器。我试图改变管道中的顺序,但同样的问题也试图使用fireChannelRead(...)和同样的问题。 谢谢
我们已经在前两节中表征并变换了不定长的输入序列。但在自然语言处理的很多应用中,输入和输出都可以是不定长序列。以机器翻译为例,输入可以是一段不定长的英语文本序列,输出可以是一段不定长的法语文本序列,例如 英语输入:“They”、“are”、“watching”、“.” 法语输出:“Ils”、“regardent”、“.” 当输入和输出都是不定长序列时,我们可以使用编码器—解码器(encoder-de
我使用apache camel Netty使用此代码将ebcdic输入转换为ascii。 任何建议或答案...
我希望将传入的Netty的消息转换为我的类的实例。为此,我使用以下: 现在,由于消息是引用计数的,我们必须在处理完它之后释放它。这是由我们正在扩展的自动完成的。 现在,既然ButeBuf已经发布,这难道不意味着支持阵列处于危险之中吗?它将被回收,我不确定我会在我的MyBuffer的数组中看到什么。 这个解码器可以安全使用吗?这是正确的编写方式吗?