为什么从未调用我的 ByteToMessageDecoder 解码方法?
Why is my ByteToMessageDecoder decode method never called?
我正在努力掌握 Netty。我在这里使用 HTTP 作为示例(我知道库中有 HTTP (de/en) 编码器,但对我来说,这个练习的重点是让我了解管道的运行方式。
我有一个简单的管道构造如下
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel){
socketChannel.pipeline().addLast(new Announcer());
socketChannel.pipeline().addLast(new Receiver());
socketChannel.pipeline().addLast(new Source());
}
});
播音员是一个 MessageToByteEncoder<String>
和 encode
方法:
@Override
protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) {
byte[] bytes = msg.getBytes(CharsetUtil.US_ASCII);
out.writeBytes(bytes);
}
来源是一个 ChannelOutboundHandlerAdapter
和 read
方法:
@Override
public void read(ChannelHanderContext ctx) {
String path = "/";
String host = "xkcd.com"
String content = "GET " + path + " HTTP/1.1\n" +
"Host: " + host + "\n" +
"\n";
ctx.writeAndFlush(content);
}
接收者是一个 ByteToMessageDecoder
和 decode
方法:
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
String e = in.toString(CharsetUtil.UTF_8);
System.err.println(e);
out.add(e);
}
我已经验证 Source 的输出是一个有效的 HTTP 请求并从 xkcd.com:80
得到响应
我看到了 Source,然后调用了 Announcer 的方法来生成请求,但是 我从未看到 Receiver 的解码方法被调用。
为什么?
在解码器实现中
You’ll find that for inbound data the channelRead
method/event is overridden. This method is called for each message that’s read from the inbound Channel . It will then call the decode()
method of the provided decoder and forward the decoded bytes to the next ChannelInboundHandler
in the pipeline.
在您的情况下,您已经覆盖了 ChannelOutboundHandlerAdapter
的 read
方法,并且您没有在该方法中调用 ctx.read()
。这意味着它将阻止调用任何 ChannelInboundHandler
的 channelRead
方法,从而阻止调用任何解码器的 decode
方法。在您的情况下 Source
class 正在阻止从频道读取。
此外,覆盖 ChannelOutboundHandlerAdapter
的读取方法的目的不应该是向通道写入内容。
下面是read方法的定义。
read(ChannelHandlerContext)
Invoked on request to read more data from the Channel
你可以阅读 Netty in action 书来更好地理解 netty。
我正在努力掌握 Netty。我在这里使用 HTTP 作为示例(我知道库中有 HTTP (de/en) 编码器,但对我来说,这个练习的重点是让我了解管道的运行方式。
我有一个简单的管道构造如下
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel){
socketChannel.pipeline().addLast(new Announcer());
socketChannel.pipeline().addLast(new Receiver());
socketChannel.pipeline().addLast(new Source());
}
});
播音员是一个 MessageToByteEncoder<String>
和 encode
方法:
@Override
protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) {
byte[] bytes = msg.getBytes(CharsetUtil.US_ASCII);
out.writeBytes(bytes);
}
来源是一个 ChannelOutboundHandlerAdapter
和 read
方法:
@Override
public void read(ChannelHanderContext ctx) {
String path = "/";
String host = "xkcd.com"
String content = "GET " + path + " HTTP/1.1\n" +
"Host: " + host + "\n" +
"\n";
ctx.writeAndFlush(content);
}
接收者是一个 ByteToMessageDecoder
和 decode
方法:
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
String e = in.toString(CharsetUtil.UTF_8);
System.err.println(e);
out.add(e);
}
我已经验证 Source 的输出是一个有效的 HTTP 请求并从 xkcd.com:80
得到响应我看到了 Source,然后调用了 Announcer 的方法来生成请求,但是 我从未看到 Receiver 的解码方法被调用。
为什么?
在解码器实现中
You’ll find that for inbound data the
channelRead
method/event is overridden. This method is called for each message that’s read from the inbound Channel . It will then call thedecode()
method of the provided decoder and forward the decoded bytes to the nextChannelInboundHandler
in the pipeline.
在您的情况下,您已经覆盖了 ChannelOutboundHandlerAdapter
的 read
方法,并且您没有在该方法中调用 ctx.read()
。这意味着它将阻止调用任何 ChannelInboundHandler
的 channelRead
方法,从而阻止调用任何解码器的 decode
方法。在您的情况下 Source
class 正在阻止从频道读取。
此外,覆盖 ChannelOutboundHandlerAdapter
的读取方法的目的不应该是向通道写入内容。
下面是read方法的定义。
read(ChannelHandlerContext)
Invoked on request to read more data from the Channel
你可以阅读 Netty in action 书来更好地理解 netty。