关键在“让丢包不影响体验”,需分工明确、结构清晰、拓扑匹配:socket 管端口进出,packet 自带上下文,按场景选单播或组播;端点管理强调接收端固定绑定、发送端随机端口;报文封装须含序列号、时间戳等元信息;分发依一对一/一对多选用单播或组播;性能上需异步处理、大缓冲、设超时。

用 DatagramSocket 和 DatagramPacket 实现高效报文分发,关键不在“不丢包”,而在“让丢包不影响体验”。核心是分工明确、结构清晰、拓扑匹配——Socket 只管端口进出,Packet 必须自带上下文,分发方式按场景选单播或组播。
端点管理:Socket 要各司其职
接收端必须绑定固定端口,发送端尽量用随机端口:
- 接收方用 DatagramSocket(6000) 显式绑定,确保音视频流能被稳定监听;
- 发送方用 DatagramSocket() 让系统自动分配临时端口,避免端口冲突或 bind 失败;
- 切忌重复 bind:带端口构造后又调
socket.bind(...)会直接抛BindException; - Windows 下刚关闭的 socket 可能因 TIME_WAIT 暂时不可重用,等几秒再试更稳妥。
报文封装:Packet 必须带元信息
原始字节数组不能直接发,得套一层可解析的结构(如 RTP):
- 每个 DatagramPacket 都要包含目标地址、端口、有效载荷,以及至少序列号和时间戳;
- 接收时用
packet.getData()取出完整字节数组,先解析 RTP 头,再决定是否缓存、跳帧或送解码; - 发送前务必确认 buffer 长度 ≥ 预期报文大小,否则会被截断;
- 接收后一定用
packet.getLength()获取真实长度,别直接用 buffer.length——UDP 报文长度是动态的。
分发拓扑:单播与组播按需切换
一对一时走单播,一对多时优先组播,别硬扛:
- 远程预览、设备控制等点对点场景,用普通 DatagramSocket + 单播 最简单可靠;
- 教室广播、监控轮播等一对多场景,改用 MulticastSocket 并加入组播地址(如
239.0.0.1),源端带宽压力直降; - 组播需网络支持 IGMP,接收端必须显式调
joinGroup()才能收包; - Android 设备默认可能禁用组播,记得声明权限
CHANGE_WIFI_MULTICAST_STATE。
性能保障:缓冲与线程不能拖后腿
音视频对延迟敏感,收发必须异步且 buffer 要够大:
- 收发操作绝不能放在主线程,建议用独立线程或线程池处理;
- 接收 buffer 建议设为 64KB 或更大,避免小包频繁触发系统调用;
- 可调
setSoTimeout(500)防止 receive 永久阻塞,配合超时重试逻辑; - 发送端若需高吞吐,可批量构造 packet 后循环 send,但注意不要压垮网卡队列。











