我需要在Go上编写多播侦听器。读取数据包时,我会遇到缠绕数据包的问题。看来我需要将IP_MULTICAST_LOOP设置为false。在Go中不容易做到。
我找到了this post。似乎应该起作用。但是我仍然可以得到同一主机的副本。应该怎么做?
ipAddr, err := net.ResolveUDPAddr("udp", groupAddress)
if err != nil {...}
iface, err := net.InterfaceByName("en0")
if err != nil {...}
conn, err := net.ListenPacket("udp4", groupAddress)
if err != nil {...}
pc := ipv4.NewPacketConn(conn)
if err := pc.JoinGroup(iface, ipAddr); err != nil {...}
if err := pc.SetMulticastLoopback(false); err != nil {...}
if loop, err := pc.MulticastLoopback(); err == nil {...}
buf := make([]byte, 1024)
for {
n, _, addr, err := pc.ReadFrom(buf)
if err != nil {...}
fmt.Printf("recv from %v: [%s] \n", addr, buf[:n])
}
[最简单的方法是在ListenMulticastUDP程序包中使用net
包装程序,正如您所指向的另一个SO答案How to set IP_MULTICAST_LOOP on multicast UDPConn in Golang中已经实际解释过的。
如果遵循ListenMulticastUDP()
的实现,您将在某个时候看到它调用setIPv4MulticastLoopback(fd, false)
。
如果需要更高级的知识,ListenMulticastUDP()
的文档建议查看https://godoc.org/golang.org/x/net/ipv4和https://godoc.org/golang.org/x/net/ipv6,它们广泛地介绍了如何在Go中进行多播。
这里有一些最小的代码(已在MacOS上测试过,但与平台无关),显示了如何使用ListenMulticastUDP()
:
func main() {
// MDNS (https://en.wikipedia.org/wiki/Multicast_DNS)
groupAddress := "224.0.0.251:5353"
ifaceName := "en0"
if err := run(groupAddress, ifaceName); err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1)
}
}
func run(groupAddr string, ifaceName string) error {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return err
}
gaddr, err := net.ResolveUDPAddr("udp", groupAddr)
if err != nil {
return err
}
conn, err := net.ListenMulticastUDP("udp", iface, gaddr)
if err != nil {
return err
}
buf := make([]byte, 1024)
for {
n, addr, err := conn.ReadFromUDP(buf)
if err != nil {
return err
}
fmt.Printf("recv %4d bytes from %v\n", n, addr)
}
}