dongliaojing0554 2017-03-30 05:52
浏览 1397
已采纳

如何在Golang中在多播UDPConn上设置IP_MULTICAST_LOOP

I need to set IP_MULTICAST_LOOP on a multicast UDP connection/socket so I can send/receive multicast packets on my local machine. This is the call that I've found which should work:

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)

However it fails with "not supported by windows". I'm pretty sure this is supported by sockets in windows, just not in the Go net package. Any idea on how I can set this flag on my connection? (I'm new to the Go language, I may have overlooked something obvious). This is on Windows, I haven't had a chance to test on Linux.

  • 写回答

1条回答 默认 最新

  • douya1248 2017-03-30 11:10
    关注

    As the doc says, net.ListenMulticastUDP is just for convenience of simple small applications. You can use golang.org/x/net/ipv4 for general purpose uses, this package offers you more options about multicast.. Actually, the source code of net.ListenMulticastUDP() sets IP_MULTICAST_LOOP to 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() is implemented for different OSes, and it's not exported. For Windows, it's in sockoptip_windows.go:

    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)))
    }
    

    Below is an example with golang.org/x/net/ipv4, you can get/set MulticastLoopback

    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
    ", 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
    ", 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
    ", loop)
            if !loop {
                if err := pc.SetMulticastLoopback(true); err != nil {
                fmt.Printf("SetMulticastLoopback error:%v
    ", err)
                }
            }
        }
    
        if _, err := conn.WriteTo([]byte("hello"), ipv4Addr); err != nil {
            fmt.Printf("Write failed, %v
    ", 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
    ", string(buf[:n]), addr)
            }
        }
    
        return
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器