如何在Golang的多播UDPConn上设置IP_多播_循环

如何在Golang的多播UDPConn上设置IP_多播_循环,go,multicast,multicastsocket,Go,Multicast,Multicastsocket,我需要在多播UDP连接/套接字上设置IP_多播_循环,以便在本地计算机上发送/接收多播数据包。这是我发现的应该有效的呼叫: l, err := net.ListenMulticastUDP("udp4", nil, addr) file, err := l.File() fd := syscall.Handle(file.Fd()) err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, 1)

我需要在多播UDP连接/套接字上设置IP_多播_循环,以便在本地计算机上发送/接收多播数据包。这是我发现的应该有效的呼叫:

l, err := net.ListenMulticastUDP("udp4", nil, addr)
file, err := l.File()
fd := syscall.Handle(file.Fd())

err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, 1)
但是,如果出现“windows不支持”,则会失败。我很确定windows中的套接字支持这一点,只是Go-net包中不支持。你知道如何在我的连接上设置这个标志吗?(我不熟悉围棋语言,我可能忽略了一些显而易见的东西)。这是在Windows上,我还没有机会在Linux上测试。

正如上面所说,
net.ListenMulticastUDP
只是为了方便简单的小应用程序。您可以用于一般用途,此软件包为您提供了有关多播的更多选项。。实际上,
net.listenmulticastup()
的源代码将
IP\u multicastup\u循环
设置为false:

func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
    if ifi != nil {
        if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
            return err 
        }   
    }   
    if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
        return err 
    }   
    if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
        return err 
    }   
    return nil 
}
setIPv4MulticastLoopback()
是为不同的操作系统实现的,它不会导出。对于Windows,它位于
sockoptip\u Windows中。转到

func setIPv4MulticastLoopback(fd *netFD, v bool) error {
    if err := fd.incref(); err != nil {
        return err 
    }   
    defer fd.decref()
    return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_IP, syscall.IP_MULTICAST_LOOP, boolint(v)))
}
下面是一个使用
golang.org/x/net/ipv4
的示例,您可以获取/设置
多播环回

package main

import (
    "fmt"
    "net"
    "golang.org/x/net/ipv4"
)

func main() {
    ipv4Addr := &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251), Port: 5352}
    conn, err := net.ListenUDP("udp4", ipv4Addr)
    if err != nil {
        fmt.Printf("ListenUDP error %v\n", err)
        return
    }

    pc := ipv4.NewPacketConn(conn)

    // assume your have a interface named wlan
    iface, err := net.InterfaceByName("wlan")
    if err != nil {
        fmt.Printf("can't find specified interface %v\n", err)
        return
    }
    if err := pc.JoinGroup(iface, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}); err != nil {
        return
    }

    // test
    if loop, err := pc.MulticastLoopback(); err == nil {
        fmt.Printf("MulticastLoopback status:%v\n", loop)
        if !loop {
            if err := pc.SetMulticastLoopback(true); err != nil {
            fmt.Printf("SetMulticastLoopback error:%v\n", err)
            }
        }
    }

    if _, err := conn.WriteTo([]byte("hello"), ipv4Addr); err != nil {
        fmt.Printf("Write failed, %v\n", err)
    }


    buf := make([]byte, 1024)
    for {
        if n, addr, err := conn.ReadFrom(buf); err != nil {
            fmt.Printf("error %v", err)
        } else {
            fmt.Printf("recv %s from %v\n", string(buf[:n]), addr)
        }
    }

    return
}

我认为stdlib ListenMulticastUDP在默认情况下禁用环回是有点愚蠢的,因为它使它完全无法用于测试目的(即,在一台测试机器上运行多个节点),并且它没有在文档中明确指出它专门禁用环回,这是不合理和令人讨厌的


是一个简单的函数,返回一个标准224.0.0.1,其中包含启用环回的任意端口。我想如果它允许您选择环回地址会更好,但对于构建局域网多播IPv4系统,这就是您所需要的。

作为参考,我在Windows 10上使用go 1.8。好的,那么我如何在自己的代码中将其设置为true,因为它没有导出?正如,
net.ListenMulticastUDP
只是为了方便简单的小型应用程序。您可以将其用于一般用途,此软件包为您提供了有关多播的更多选项。您有如何实现这一点的示例吗?我一直在努力寻找并解决这个问题。太好了,谢谢!我还了解到,您可以通过nil而不是网络接口,这样它就可以监听所有数据。