UDP通信必须使用NioDatagramChannel而非NioSocketChannel,因其基于无连接数据报,需用DatagramPacket封装ByteBuf和地址,且每次收发后须手动release以避免内存泄漏。

UDP收发必须用 NioDatagramChannel,不是 NioSocketChannel
Netty 的 UDP 通信和 TCP 完全不同路径,NioSocketChannel 只处理面向连接的字节流,强行套用会直接抛 UnsupportedOperationException 或绑定失败。UDP 是无连接、基于数据报的,底层必须走 NioDatagramChannel,它封装的是 DatagramChannel,支持 send()/receive() 和 connect()(仅用于过滤地址,非真正连接)。
实操建议:
- 启动时用
Bootstrap(不是ServerBootstrap),因为 UDP 没有“服务端/客户端”严格区分,只有主动发或被动收 -
channel(NioDatagramChannel.class)必须显式指定,否则默认用NioSocketChannel - 绑定端口用
bind(8080),不是connect();想限制只收某地址的数据,才调channel.connect(new InetSocketAddress("127.0.0.1", 9000))
DatagramPacket 是唯一数据载体,不能用 ByteBuf 直传
UDP 收发必须包装成 DatagramPacket,它内部持有一个 ByteBuf 和一个 InetSocketAddress。你不能像 TCP 那样直接 ctx.writeAndFlush(byteBuf) —— 这会触发 IllegalArgumentException: unsupported message type。
实操建议:
- 接收时,
channelRead()回调里拿到的就是DatagramPacket,用packet.content()取ByteBuf,packet.sender()拿远端地址 - 发送时,必须 new
DatagramPacket(content, recipient),recipient不能为空;广播需设 socket 为setBroadcast(true)并用255.255.255.255地址 -
DatagramPacket是一次性的,每次发送都要新建;复用ByteBuf可以,但别复用整个 packet 对象
空包、分片、乱序问题:UDP 协议层不保证,Netty 不补救
Netty 只做 I/O 封装,不解决 UDP 天然缺陷。收不到包、收到重复包、顺序错乱、单包超 64KB 被截断 —— 这些都不是 Netty 的 bug,而是 UDP 本身行为。常见现象包括:recvfrom() 返回 0 字节(空包)、ChannelHandlerContext.fireChannelRead() 突然没反应(包被内核丢弃)、日志里反复出现 java.io.IOException: Message too long(应用层发超限)。
实操建议:
- 应用层必须自己加长度头、校验和、序列号;别依赖 Netty 自动拆合包
- 单包内容严格控制在 512–1400 字节(避开 IP 分片),超过就分包并设计重传逻辑
- 用
SO_RCVBUF和SO_SNDBUF调大系统缓冲区(channel.config().setOption(ChannelOption.SO_RCVBUF, 1024 * 1024)),缓解突发丢包
线程模型与内存泄漏:DatagramPacket 必须释放
UDP 的 DatagramPacket 持有 ByteBuf,而 Netty 默认用堆外内存(PooledByteBufAllocator)。如果忘记释放,每次收包都会吃掉一块未回收内存,压测几分钟就 OOM。这不是 GC 能解决的问题。
实操建议:
- 只要用了
packet.content(),就必须在处理完后调packet.release()(它会级联释放内部ByteBuf) - 不要在
channelReadComplete()里统一释放 —— 此时 packet 可能已被后续 handler 复用或修改 - 写 handler 时优先继承
SimpleChannelInboundHandler<DatagramPacket>,它的channelRead0()会在返回后自动 release;但注意:一旦你在方法里把packet.content()传出到其他线程,就得手动 retain
最易被忽略的一点:广播场景下,同一个 DatagramPacket 可能被多个 handler 处理,release 时机必须对齐业务生命周期,而不是机械套用模板。










