
udp 是无连接协议,`listenudp` 创建的连接无法直接使用 `write` 发送响应,必须通过 `readfromudp` 获取客户端地址,再用 `writetoudp` 显式指定目标地址才能实现双向通信。
在 Go 中使用 net.ListenUDP 启动 UDP 服务端时,得到的是一个 *net.UDPConn,它不维护连接状态,因此调用 conn.Write([]byte{...}) 实际上等价于向一个未指定目标地址的“空连接”写入数据——该操作会静默失败(或返回 nil 错误但被忽略),Wireshark 无法捕获任何发出的报文,正是这个原因。
正确做法是:使用 ReadFromUDP 接收数据的同时获取发送方的网络地址(*net.UDPAddr),再通过 WriteToUDP 将响应明确发送回该地址。以下是修正后的完整服务端(Node 1)代码:
func main() {
addr := &net.UDPAddr{Port: 7000, IP: net.ParseIP("127.0.0.1")}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Println("UDP server listening on :7000")
for {
buf := make([]byte, 1024) // 建议增大缓冲区,避免截断
n, clientAddr, err := conn.ReadFromUDP(buf)
if err != nil {
log.Printf("Read error: %v", err)
continue
}
msg := strings.TrimSpace(string(buf[:n]))
fmt.Printf("Received from %v: %q\n", clientAddr, msg)
reply := []byte("sending back")
_, err = conn.WriteToUDP(reply, clientAddr)
if err != nil {
log.Printf("WriteToUDP error to %v: %v", clientAddr, err)
}
}
}客户端(Node 2)可保持原样(使用 net.Dial 亦可,因其内部会绑定临时端口并记录对端地址),但建议显式处理错误并增加超时控制:
1.修正BUG站用资源问题,优化程序2.增加关键词搜索3.修改报价4.修正BUG 水印问题5.修改上传方式6.彻底整合论坛,实现一站通7.彻底解决群发垃圾信息问题。注册会员等发垃圾邮件7.彻底解决数据库安全9.修改交易方式.增加网站担保,和直接交易两中10.全站可选生成html.和单独新闻生成html(需要装组建)11. 网站有10中颜色选择适合不同的行业不同的颜色12.修改竞价格排名方式13.修
func main() {
conn, err := net.Dial("udp", "127.0.0.1:7000")
if err != nil {
panic(err)
}
defer conn.Close()
_, _ = conn.Write([]byte("first send"))
buf := make([]byte, 1024)
conn.SetReadDeadline(time.Now().Add(3 * time.Second))
n, err := conn.Read(buf)
if err != nil {
log.Fatal("Read timeout or error:", err)
}
fmt.Println("Reply:", string(buf[:n]))
}⚠️ 注意事项:
- ReadFromUDP 和 WriteToUDP 是成对使用的标准模式,不可混用 Read/Write;
- 缓冲区大小应足够容纳典型 UDP 报文(通常 ≥512 字节),避免因截断导致协议解析失败;
- 务必检查所有 I/O 错误,尤其是 WriteToUDP 可能因目标不可达、ICMP 目标不可达等返回错误;
- UDP 不保证送达、顺序和去重,业务层需自行处理可靠性(如重传、序列号);
- 若需多客户端并发响应,UDPConn 本身是并发安全的,无需额外加锁。
通过上述改造,即可在无连接的 UDP 基础上,稳定实现请求-响应式的双向通信。









