udp广播需显式启用so_broadcast选项,发送端调用setbroadcast(true),接收端绑定通配地址;推荐dialudp发送、listenudp接收;子网广播地址比255.255.255.255更可靠;需设置读写缓冲区并避免goroutine阻塞导致丢包。

UDP广播必须显式启用 SO_BROADCAST 选项
Go 的 net.UDPConn 默认禁止发送广播包,哪怕目标地址是 255.255.255.255 或子网广播地址(如 192.168.1.255),不设这个选项会静默失败或报 operation not permitted 错误。
- 发送端必须调用
conn.SetWriteBuffer()前或后执行conn.SetBroadcast(true);顺序无关,但缺一不可 - 接收端不需要设
SetBroadcast—— 只要绑定到通配地址(如:8888),系统自动接收广播包 - Linux/macOS 下通常默认允许;Windows 某些策略或防火墙可能拦截,需验证本地网络策略
用 DialUDP 还是 ListenPacket?选错就收不到广播
发送广播只能用 DialUDP 或 ListenPacket 配合 WriteTo;ListenUDP 创建的连接不能直接 Write 广播地址,它只支持向已知远端写(WriteToUDP 才行)。
- 推荐发送端统一用
net.DialUDP("udp", nil, addr):简洁、语义明确、自动处理 socket 绑定 - 接收端必须用
net.ListenUDP("udp", &net.UDPAddr{Port: 8888})或net.ListenPacket("udp", ":8888"),不能写死 IP(如127.0.0.1:8888),否则收不到其他机器发来的广播 - 别在
for循环里反复ResolveUDPAddr——解析结果可复用,频繁调用无意义且略拖慢启动
广播地址怎么填?255.255.255.255 不一定管用
255.255.255.255 是受限广播地址,多数路由器和部分交换机默认丢弃,仅在直连子网有效;而子网广播地址(如 192.168.1.255)更可靠,但得知道本机所在子网。
- 硬编码子网广播地址最稳妥,适合固定局域网环境(如内网 IoT 设备发现)
- 若需自动适配,得先用
net.Interfaces()查本机活跃网卡,再遍历Interface.Addrs()解析出 IPv4 + 子网掩码,手动计算广播地址——别指望net.ParseIP("255.255.255.255")能解决所有问题 - 某些云主机或 Docker 网络中,
255.255.255.255完全无效,此时必须走子网广播或改用组播(224.0.0.1)
接收端丢包?别在 ReadFromUDP 里做重逻辑
UDP 本身无重传、无顺序保证,但应用层丢包主因常是接收协程阻塞——比如在 ReadFromUDP 后立刻解析 JSON、写文件或 HTTP 请求,导致下一次读被延迟,内核缓冲区溢出。
立即学习“go语言免费学习笔记(深入)”;
- 每次
ReadFromUDP收到数据,应立刻起go func() { ... }()处理,主线程马上回到循环继续收包 - buffer 切片必须在循环内重新切(如
buf[:n]),不能把整个buf传进 goroutine——多个并发 goroutine 会踩同一块内存 - 建议设置 socket 接收缓冲区:
conn.SetReadBuffer(65536),尤其在高频率广播场景下能明显降低丢包率










