默认netty udp接收DatagramPacket字节数最大是2048,如果数据大,超过这个限制,就会报错,抛出异常,虽然这个包解析失败,不会影响其他包的解析,但是总得来说,这种失败是不利于数据收集的。
1、pom文件
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.75.Final</version>
</dependency>
2、服务端实现 UdpServerHandler
package com.example.demo.udp;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
public class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
String msg = packet.content().toString(CharsetUtil.UTF_8);
System.err.println("服务端接收消息:" + msg);
if (msg.startsWith("1")) {
ctx.write(new DatagramPacket(
Unpooled.copiedBuffer("QOTM:111111", CharsetUtil.UTF_8), packet.sender()));
} else {
ctx.write(new DatagramPacket(
Unpooled.copiedBuffer("QOTM:2222222222", CharsetUtil.UTF_8), packet.sender()));
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
// We don't close the channel because we can keep serving requests.
}
}
UdpServer
package com.example.demo.udp;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
/**
* A UDP server that responds to the QOTM (quote of the moment) request to a {@link UdpClient}.
* <p>
* Inspired by <a href="https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
* Java tutorial</a>.
*/
public final class UdpServer {
private static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UdpServerHandler());
b.bind(PORT).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}
}
}
3、客户端实现
UdpClientHandler
package com.example.demo.udp;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
public class UdpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
String response = msg.content().toString(CharsetUtil.UTF_8);
System.err.println("客户端接收到消息:" + response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
UdpClient
package com.example.demo.udp;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.SocketUtils;
/**
* A UDP broadcast client that asks for a quote of the moment (QOTM) to {@link UdpServer}.
* <p>
* Inspired by <a href="https://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
* Java tutorial</a>.
*/
public final class UdpClient {
static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UdpClientHandler());
Channel ch = b.bind(0).sync().channel();
// Broadcast the QOTM request to port 8080.
ch.writeAndFlush(new DatagramPacket(
Unpooled.copiedBuffer("4444444", CharsetUtil.UTF_8),
SocketUtils.socketAddress("255.255.255.255", PORT))).sync();
ch.closeFuture().await();
} finally {
group.shutdownGracefully();
}
}
}
解决 netty udp接收DatagramPacket字节数最大是2048这个问题,只需要一行代码
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
服务端代码修改如下
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
// 设置读缓冲区为 10M
.option(ChannelOption.SO_RCVBUF, 1024 * 1024*10)
// 设置写缓冲区为1M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024)
//解决最大接收2048个字节
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
.handler(new UdpServerHandler());
b.bind(PORT).sync().channel().closeFuture().await();
客户端代码修改如下
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
// 设置读缓冲区为 10M
.option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 10)
// 设置写缓冲区为1M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024)
//解决最大接收2048个字节
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
.handler(new UdpClientHandler());
Channel ch = b.bind(0).sync().channel();