gpt4 book ai didi

java - 使用 Netty 的长度前缀框架 - 无法设置 LengthFieldPrepender/Decoder

转载 作者:行者123 更新时间:2023-11-30 07:53:28 26 4
gpt4 key购买 nike

在我简单的 udp netty 应用程序中,我尝试使用 netty 启用长度前缀框架。我正在使用一个 channel 来处理传入消息和发布新消息 (#send)。

public class Server {

private static final int FRAME_LENGTH_PREFIX_LENGTH = 2;
private static final int FRAME_MAX_LENGTH = 64 * 1024;

private static final LengthFieldPrepender frameLengthPrefixPrepender =
new LengthFieldPrepender(FRAME_LENGTH_PREFIX_LENGTH, true);
private static final LengthFieldBasedFrameDecoder frameLengthPrefixDecoder =
new LengthFieldBasedFrameDecoder(FRAME_MAX_LENGTH, 0, FRAME_LENGTH_PREFIX_LENGTH,
-FRAME_LENGTH_PREFIX_LENGTH, FRAME_LENGTH_PREFIX_LENGTH, true);

private final InetSocketAddress me;

private final Channel serverChannel;

private Server(ServerBuilder builder) {
this.serverChannel = buildServerChannel(builder.inetAddress, builder.port, builder.channel,
builder.eventLoopExecutors, builder.channelOptions, builder.loggerLevel);

this.me = new InetSocketAddress(builder.inetAddress, builder.port);
}

private Channel buildServerChannel(InetAddress inetAddress, Integer port,
Class<? extends Channel> channel, EventLoopGroup eventExecutors,
Map<ChannelOption, Object> opts, LogLevel logLevel) {

val b = new Bootstrap();

b.group(eventExecutors)
.channel(channel);
opts.forEach(b::option);

b.handler(new ChannelInitializer<DatagramChannel>() {
@Override
protected void initChannel(DatagramChannel ch) throws Exception {
val pipe = ch.pipeline();

if (logLevel != null)
pipe.addLast(new LoggingHandler(logLevel));

// pipe.addLast(frameLengthPrefixDecoder); // disabled for testing purposes

pipe.addLast(new SimpleChannelInboundHandler<DatagramPacket>() {

@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
ByteBuf buf = (ByteBuf) msg.copy().content();
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, CharsetUtil.UTF_8);
System.out.println("SimpleChannelInboundHandler<DatagramPacket> : "+body);
}
});

pipe.addLast(frameLengthPrefixPrepender);
}
});
return b.bind(inetAddress, port).syncUninterruptibly().channel();
}

private ChannelFuture send(InetSocketAddress dest, ByteBuf data) {
val datagramPacket = new DatagramPacket(data, dest, me);

return serverChannel.writeAndFlush(datagramPacket);
}
}

我正在尝试发送一条“你好”消息:

public static void main(String[] a) throws UnknownHostException {
Server build = new Server().loggerLevel(LogLevel.DEBUG).build();
build.send(new InetSocketAddress(InetAddress.getByName("localhost"), 1080), Unpooled.copiedBuffer("HELLO".getBytes()));
}

我期望的是:

+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 07 48 45 4c 4c 4f |..HELLO |
^^^^^ prefix
+--------+-------------------------------------------------+----------------+

尽管如此,它仍然是:

+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 45 4c 4c 4f |HELLO |
+--------+-------------------------------------------------+----------------+

我还尝试通过放置断点 LengthFieldPrepender#encode 和 LengthFieldBasedFrameDecoder#decode 来调试 LengthFieldPrepender/LengthFieldBasedFrameDecoder,发现这些方法根本没有被调用。

我用这种方法制作了几个 hello world netty tcp 应用程序,从来没有遇到过问题。我觉得我做错了什么有一个非常简单的解释,但我正在努力寻找它。

最佳答案

这里的问题是您直接将 DatagramPacket 写入 channel 的管道,而出站处理程序 LengthFieldPrepender 只接受 ByteBuf 类型的对象。因此,数据报会跳过编码器。

关于java - 使用 Netty 的长度前缀框架 - 无法设置 LengthFieldPrepender/Decoder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44734883/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com