Golang中UDP广播的实现与问题求助
Golang中UDP广播的实现与问题求助 你好,
我正在尝试通过UDP广播与另一台通过以太网电缆直接连接的计算机进行通信。
以下是服务器端代码:
package main
import (
"fmt"
"net"
)
func main() {
//本地地址
la, err := net.ResolveUDPAddr("udp4", "0.0.0.0:8000")
if err != nil {
fmt.Println(err)
return
}
//监听
c, err := net.ListenUDP("udp4", la)
if err != nil {
fmt.Println(err)
return
}
//读取
bs := make([]byte, 4096)
n, ra, err := c.ReadFromUDP(bs)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(n, ra)
}
以下是客户端代码:
package main
import (
"fmt"
"net"
)
func main() {
//本地地址
la, err := net.ResolveUDPAddr("udp4", "1.2.3.4:8000")
if err != nil {
fmt.Println(err)
return
}
ra, err := net.ResolveUDPAddr("udp4", "255.255.255.255:8000")
if err != nil {
fmt.Println(err)
return
}
//拨号连接
c, err := net.DialUDP("udp4", la, ra)
if err != nil {
fmt.Println(err)
return
}
//写入
n, err := c.Write([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%d bytes written\n", n)
}
情况1:如果这些电脑有相同的网关地址,则没有问题。 情况2:如果这些电脑在同一网络子组中,例如 1.2.3.4 和 1.2.3.5,也没有问题。 情况3:如果这些电脑具有随机的IP地址,例如 1.2.3.4 和 4.3.2.1,我就无法进行通信。
我还检查了所有网络接口都具备 net.FlagBroadcast 标志。
我计划使用这种通信方式来查找另一台电脑的IP地址,该电脑将拥有一个随机的静态IP地址,并且将通过以太网电缆直接连接到我的电脑。许多设备都有这种“查找设备”的功能。
UDP广播方法是正确的吗?
需要帮助 🙂
此致
更多关于Golang中UDP广播的实现与问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
听起来很不错,你介意分享一下使用原始以太网帧的最小测试用例吗?
更多关于Golang中UDP广播的实现与问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
谢谢,
我通过使用原始以太网帧解决了我的问题。
此致
如果路由配置正确,UDP广播将正常工作。 从连接到不路由该地址的网络的随机地址发出的UDP广播将无法工作。 你可能需要使用类似ARP的协议来代替。
在Go中实现UDP广播时,你遇到的情况3(不同子网)无法通信是正常的网络行为。UDP广播默认只在本地子网内有效,无法跨子网传播。对于直接以太网连接的情况,需要确保两台计算机在同一IP子网中。
以下是修改后的服务器端代码,可以监听所有接口的广播:
package main
import (
"fmt"
"net"
)
func main() {
// 监听所有接口的8000端口
addr, err := net.ResolveUDPAddr("udp4", ":8000")
if err != nil {
fmt.Println("ResolveUDPAddr error:", err)
return
}
conn, err := net.ListenUDP("udp4", addr)
if err != nil {
fmt.Println("ListenUDP error:", err)
return
}
defer conn.Close()
fmt.Println("Server listening on :8000")
// 设置广播权限
conn.SetReadBuffer(1024 * 1024)
buffer := make([]byte, 4096)
for {
n, clientAddr, err := conn.ReadFromUDP(buffer)
if err != nil {
fmt.Println("ReadFromUDP error:", err)
continue
}
fmt.Printf("Received %d bytes from %s: %v\n",
n, clientAddr.String(), buffer[:n])
// 可以回复消息
_, err = conn.WriteToUDP([]byte("ACK"), clientAddr)
if err != nil {
fmt.Println("WriteToUDP error:", err)
}
}
}
以下是修改后的客户端代码,使用更灵活的广播方式:
package main
import (
"fmt"
"net"
"time"
)
func main() {
// 获取广播地址
broadcastAddr, err := net.ResolveUDPAddr("udp4", "255.255.255.255:8000")
if err != nil {
fmt.Println("ResolveUDPAddr error:", err)
return
}
// 创建连接,不绑定特定本地地址
conn, err := net.DialUDP("udp4", nil, broadcastAddr)
if err != nil {
fmt.Println("DialUDP error:", err)
return
}
defer conn.Close()
// 设置广播权限
conn.SetWriteBuffer(1024 * 1024)
// 发送广播消息
message := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
for i := 0; i < 5; i++ {
n, err := conn.Write(message)
if err != nil {
fmt.Println("Write error:", err)
return
}
fmt.Printf("Sent %d bytes via broadcast\n", n)
time.Sleep(1 * time.Second)
}
}
对于直接电缆连接的情况,建议使用以下方法:
-
确保在同一子网:为两台计算机手动配置同一子网的IP地址,例如:
- 计算机A: 192.168.1.10/24
- 计算机B: 192.168.1.20/24
-
使用更可靠的设备发现方法:
package main
import (
"fmt"
"net"
"time"
)
func discoverDevices() {
// 尝试多个可能的广播地址
broadcastAddresses := []string{
"255.255.255.255:8000",
"192.168.1.255:8000",
"192.168.0.255:8000",
"10.255.255.255:8000",
}
for _, addr := range broadcastAddresses {
go tryBroadcast(addr)
}
time.Sleep(10 * time.Second)
}
func tryBroadcast(addr string) {
broadcastAddr, _ := net.ResolveUDPAddr("udp4", addr)
conn, err := net.DialUDP("udp4", nil, broadcastAddr)
if err != nil {
return
}
defer conn.Close()
conn.Write([]byte("DISCOVER"))
}
- 使用多播(组播)作为替代方案:
package main
import (
"fmt"
"net"
)
func multicastExample() {
// 加入多播组
multicastAddr, _ := net.ResolveUDPAddr("udp4", "224.0.0.1:9999")
localAddr, _ := net.ResolveUDPAddr("udp4", ":9999")
conn, err := net.ListenMulticastUDP("udp4", nil, multicastAddr)
if err != nil {
fmt.Println("ListenMulticastUDP error:", err)
return
}
defer conn.Close()
// 监听多播消息
buffer := make([]byte, 1024)
for {
n, src, err := conn.ReadFromUDP(buffer)
if err != nil {
continue
}
fmt.Printf("Multicast from %s: %s\n", src, buffer[:n])
}
}
UDP广播确实是实现设备发现的常用方法,但需要确保网络配置正确。对于直接电缆连接,最可靠的方法是手动配置IP地址在同一子网,或者使用链路本地地址(169.254.0.0/16)。


