跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Go语言UDP网络编程_Golang数据报通信实战详解

Go UDP服务器必须用ReadFromUDP获取客户端真实地址并配对WriteToUDP发送响应,监听地址需用":端口"而非"localhost:端口"以接收外网包,缓冲区建议1400字节,避免conn.Write等错误调用。 UDP 在 Go 里不是“连上再发”,而是“收得到才发得对”——
ReadFromUDP
返回的
*UDPAddr
是唯一可信的客户端地址,硬编码、复用监听地址或调用
conn.Write
都会发错甚至编译失败。 ListenUDP 绑定地址写错,外部机器根本连不上 Go 的
net.ListenUDP
不像 TCP 那样默认监听所有接口。写成
"localhost:8080"
或
"127.0.0.1:8080"
只绑定回环地址,局域网其他设备的 UDP 包压根进不来。 正确做法是用
":8080"
(等价于
"0.0.0.0:8080"
),监听所有 IPv4 接口 若需限定网卡,显式写具体 IP,如
"192.168.1.100:8080"
调试时可用
nc -u 127.0.0.1 8080
验证本地通,再用另一台机器
echo "test" | nc -u $SERVER_IP 8080
测外网 防火墙常被忽略:Linux 上检查
sudo ufw status
,macOS 留意“防火墙”设置是否拦截了 UDP ReadFromUDP 和 WriteToUDP 必须配对使用
UDPConn
没有连接状态,
conn.RemoteAddr()
永远是
nil
;每次收到包,
ReadFromUDP
才返回真实的发送方地址,这个
*UDPAddr
必须原样传给下一次
WriteToUDP
。 错误写法:
conn.Write([]byte("ack"))
→ 编译报错:
UDPConn.Write undefined
错误写法:
conn.WriteToUDP([]byte("ack"), &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345})
→ 地址写死,响应发给错误客户端 正确模式:先
n, addr, err := conn.ReadFromUDP(buf)
,再
conn.WriteToUDP([]byte("ack"), addr)
空包要过滤:
if n == 0 { continue }
,否则
json.Unmarshal(buf[:0], &v)
可能 panic 或解出零值 并发读写 UDPConn 的安全边界
WriteToUDP
是线程安全的,多个 goroutine 可并发调用;但
ReadFromUDP
是阻塞 I/O,不能在单个 goroutine 里串行处理——否则整个服务卡死。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 立即学习 “ go语言免费学习笔记(深入) ”; 推荐结构:一个 goroutine 循环
ReadFromUDP
,把
buf[:n]
和
addr
发到
chan struct{ data []byte; from *UDPAddr }
Worker pool 处理业务逻辑(如解析、查表、生成响应),再统一用
conn.WriteToUDP
回复 避免在 worker 中直接 close
conn
或重复
defer conn.Close()
,容易导致
use of closed network connection
缓冲区大小建议设为 1400–1500 字节(避开 IP 分片),别用
65507
—— 内核接收队列溢出比 Go 层截断更难排查 为什么本地能通、线上一跑就丢包? 丢包往往不在 Go 代码里,而在系统层和节奏错配:Linux 默认 UDP 接收缓冲区小(常为 212992 字节),如果 Go 程序读得太慢,内核直接丢弃新包,且不通知用户态。 检查当前值:
sysctl net.core.rmem_max
,临时调大:
sudo sysctl -w net.core.rmem_max=4194304
Go 层主动调大:
conn.SetReadBuffer(4 * 1024 * 1024)
(需在
ListenUDP
后立即设) 不要让
ReadFromUDP
被长耗时逻辑阻塞:比如在 handler 里同步调用 HTTP API 或数据库查询,应异步化或加超时 监控指标:定期记录
netstat -s | grep -A 5 "Udp:"
中的
packet receive errors
和
receive buffer errors
UDP 的“无连接”不是省事,是把连接管理、重传、去重、顺序保障全甩给业务层。Go 标准库只保证你能拿到原始数据报和源地址——剩下的,得自己画线、标号、计时、丢弃、重试。

相关文章