DatagramChannel是Java NIO中实现非阻塞UDP通信的核心类,需configureBlocking(false)、bind端口、注册Selector OP_READ;send()需指定目标地址并flip缓冲区,receive()返回源地址且需clear缓冲区,推荐65536字节直接缓冲区。

Java NIO 中的 DatagramChannel 是实现 UDP 通信的核心类,它支持非阻塞 I/O,适合高并发、低延迟的无连接数据报传输场景。与传统阻塞式 DatagramSocket 相比,它可配合 Selector 实现单线程管理多个 UDP 端口,但需注意 UDP 本身不保证顺序、可靠性和重复性。
创建并绑定 DatagramChannel
UDP 是无连接协议,DatagramChannel 不需要显式“连接”,但必须绑定本地端口才能接收数据。若不绑定,系统会随机分配临时端口,导致无法稳定监听。
- 调用
DatagramChannel.open()获取通道实例 - 设置为非阻塞模式(如需配合 Selector):
channel.configureBlocking(false) - 绑定本地地址:
channel.bind(new InetSocketAddress("0.0.0.0", 8080));绑定0.0.0.0表示监听所有网卡,也可指定具体 IP - 若仅用于发送(不接收),可跳过 bind,但多数服务端场景必须绑定
发送 UDP 数据报
发送时需明确目标地址(IP + 端口),每次 send 都是独立的数据报,不维护任何状态。
- 准备
ByteBuffer,写入待发送数据:buffer.flip()后调用channel.send(buffer, remoteAddr) -
remoteAddr是InetSocketAddress,例如new InetSocketAddress("127.0.0.1", 9090) - send 返回实际发送字节数(可能小于 buffer 容量),若返回 0 表示未就绪(非阻塞模式下常见)
- 无需预先 connect,每个 send 可发往不同地址
接收 UDP 数据报
接收使用 receive(ByteBuffer),它会将收到的数据填入 buffer,并返回发送方地址(可用于响应)。
立即学习“Java免费学习笔记(深入)”;
- 调用
channel.receive(buffer),buffer 需提前clear() - 方法返回值为接收到的字节数,若为
null表示无数据可读(非阻塞模式下) - 返回的
InetSocketAddress包含源 IP 和端口,是响应的关键依据 - 注意 buffer 大小应足够容纳最大可能的数据报(通常不超过 64KB,推荐设为 65536)
配合 Selector 实现多路复用(可选)
虽然 UDP 本身无连接,但一个 Selector 可同时监控多个 DatagramChannel 的读就绪事件,适用于多端口监听或混合 TCP/UDP 场景。
- 确保 channel 已 configureBlocking(false)
- 注册 OP_READ:
channel.register(selector, SelectionKey.OP_READ) - 在 select 循环中,对就绪的 key 调用
channel.receive(buffer)即可 - UDP 不支持 OP_WRITE 就绪通知(因为 send 不会真正“阻塞”),所以一般只关注 OP_READ
不复杂但容易忽略:记得处理 ICMP 错误包(如端口不可达),JVM 默认会将部分 ICMP 报告为 IOException;另外,UDP 数据报大小受 MTU 限制,超长会被分片,建议控制在 1400 字节以内以避免丢包。


















