在我的简单udp netty应用程序中,我正在尝试使用netty启用长度前缀框架。我正在使用一个通道处理传入消息和发出新消息(#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);
}
}
我正在尝试发送“Hello”消息:
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/LengthFieldBasedFrameDecoder
来调试LengthFieldPrepender#encode and LengthFieldBasedFrameDecoder#decode
,并发现这些方法根本没有被调用。
我以这种方式制作了几个hello world netty tcp应用程序并且从未出现过问题。我觉得有一个非常简单的解释我做错了什么,但我很难找到它。
答案 0 :(得分:3)
这里的问题是您直接将DatagramPacket写入通道的管道,而出站处理程序LengthFieldPrepender只接受ByteBuf类型的对象。因此,数据报会跳过编码器。