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

我需要在多播UDP连接/套接字上设置IP_MULTICAST_LOOP,以便可以在本地计算机上发送/接收多播数据包 。 这是我发现的应该可以使用的呼叫:</ p>

  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)
</ code> </ pre>

但是由于“ Windows不支持”而失败。 我很确定Windows的套接字支持此功能,只是Go net程序包不支持。 关于如何在连接上设置此标志的任何想法吗? (我是Go语言的新手,我可能忽略了一些显而易见的东西)。 这是在Windows上,我没有机会在Linux上进行测试。</ p>
</ div>

展开原文

原文

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.

dpbl91234
dpbl91234 作为参考,我在Windows10上使用go1.8。
3 年多之前 回复

1个回答

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
}
download1323
download1323 完美,谢谢! 我还了解到,您可以通过nil代替网络接口,这样它就可以监听所有内容。
3 年多之前 回复
dongzhu6900
dongzhu6900 看到我编辑的答案。
3 年多之前 回复
dtvfxzq3802
dtvfxzq3802 您是否有一个完成此事的示例? 我已经尝试搜索并弄清楚了一段时间。
3 年多之前 回复
duanping3587
duanping3587 正如文档所说,net.ListenMulticastUDP只是为了方便简单的小型应用程序。 您可以将golang.org/x/net/ipv4用作常规用途,此软件包为您提供了有关多播的更多选项。
3 年多之前 回复
douqiaolong0528
douqiaolong0528 好的,既然没有导出,如何在自己的代码中将其设置为true?
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐