无法使用 Netty UDP 和 SimpleChannelInboundHandler 在指定地址上发送消息
Can't send message on specified address with Netty UDP and SimpleChannelInboundHandler
我有 Netty 服务器,它侦听某个端口并对传入消息发送响应。服务器实现:
@Override
public void run() {
final NioEventLoopGroup group = new NioEventLoopGroup();
try {
log.info("Started listening logs ...");
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
public void initChannel(final NioDatagramChannel nioDatagramChannel) {
ChannelPipeline channelPipeline = nioDatagramChannel.pipeline();
channelPipeline.addLast(encryptedPacketHandlerChain);
}
});
// Bind and start to accept incoming connections.
InetAddress address = InetAddress.getByName("localhost");
bootstrap.bind(address, LOG_PORT).sync().channel().closeFuture().await();
} catch (Exception e) {
log.error("Unexpected error happened", e);
} finally {
System.out.print("Stop server");
}
}
EncryptedPacketHandlerChain 实现:
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) {
final String hostAddress = datagramPacket.sender().getAddress().getHostAddress();
final ByteBuf byteBuffer = datagramPacket.content();
final int receivedPacketLength = byteBuffer.readableBytes();
final byte[] receivedPacket = new byte[receivedPacketLength];
byteBuffer.readBytes(receivedPacket);
EncryptedPacket encryptedPacket = EncryptedPacket.fromBytes(receivedPacket);
byte[] response = EncryptedPacket.toBytes(handle(encryptedPacket, hostAddress));
System.out.println("Response\n" + Arrays.toString(response));
ByteBuf data = ctx.alloc().buffer(response.length);
data.writeBytes(response);
InetSocketAddress socketAddress = datagramPacket.sender();
ctx.write(new DatagramPacket(data, socketAddress));
ctx.flush();
System.out.println("Send to " + socketAddress);
}
这是我在官方netty中看到的非常简单的实现docs。但是在我从 127.0.0.2 主机地址上的本地发件人发送请求后,我没有得到 Netty 服务器的响应。
当我使用 java.net DatagramSocket 发送响应时,一切正常,但我需要从同一个套接字(即 Netty)响应发件人地址和端口。我的代码有什么问题?
UPD: 我需要在指定地址和指定端口上发送来自 netty 的响应,我可以从收入数据报包中获得。
您应该检查写入是否失败,如果是,原因是:
...
ctx.writeAndFlush(new DatagramPacket(data, socketAdress)).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (!f.isSuccess()) {
f.cause().printStackTrace();
}
}
});
我发现 in this example 如果我将刷新移动到覆盖的 channelReadComplete 方法,它会起作用:
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
很奇怪API。
我检查了@Norman Maurer 代码,它也可以工作。
我有 Netty 服务器,它侦听某个端口并对传入消息发送响应。服务器实现:
@Override
public void run() {
final NioEventLoopGroup group = new NioEventLoopGroup();
try {
log.info("Started listening logs ...");
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
public void initChannel(final NioDatagramChannel nioDatagramChannel) {
ChannelPipeline channelPipeline = nioDatagramChannel.pipeline();
channelPipeline.addLast(encryptedPacketHandlerChain);
}
});
// Bind and start to accept incoming connections.
InetAddress address = InetAddress.getByName("localhost");
bootstrap.bind(address, LOG_PORT).sync().channel().closeFuture().await();
} catch (Exception e) {
log.error("Unexpected error happened", e);
} finally {
System.out.print("Stop server");
}
}
EncryptedPacketHandlerChain 实现:
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket datagramPacket) {
final String hostAddress = datagramPacket.sender().getAddress().getHostAddress();
final ByteBuf byteBuffer = datagramPacket.content();
final int receivedPacketLength = byteBuffer.readableBytes();
final byte[] receivedPacket = new byte[receivedPacketLength];
byteBuffer.readBytes(receivedPacket);
EncryptedPacket encryptedPacket = EncryptedPacket.fromBytes(receivedPacket);
byte[] response = EncryptedPacket.toBytes(handle(encryptedPacket, hostAddress));
System.out.println("Response\n" + Arrays.toString(response));
ByteBuf data = ctx.alloc().buffer(response.length);
data.writeBytes(response);
InetSocketAddress socketAddress = datagramPacket.sender();
ctx.write(new DatagramPacket(data, socketAddress));
ctx.flush();
System.out.println("Send to " + socketAddress);
}
这是我在官方netty中看到的非常简单的实现docs。但是在我从 127.0.0.2 主机地址上的本地发件人发送请求后,我没有得到 Netty 服务器的响应。 当我使用 java.net DatagramSocket 发送响应时,一切正常,但我需要从同一个套接字(即 Netty)响应发件人地址和端口。我的代码有什么问题?
UPD: 我需要在指定地址和指定端口上发送来自 netty 的响应,我可以从收入数据报包中获得。
您应该检查写入是否失败,如果是,原因是:
...
ctx.writeAndFlush(new DatagramPacket(data, socketAdress)).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture f) {
if (!f.isSuccess()) {
f.cause().printStackTrace();
}
}
});
我发现 in this example 如果我将刷新移动到覆盖的 channelReadComplete 方法,它会起作用:
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
很奇怪API。 我检查了@Norman Maurer 代码,它也可以工作。