многоадресные петли - PullRequest
       31

многоадресные петли

0 голосов
/ 03 марта 2020

Мне нужно написать многоадресный прослушиватель на Go. Я сталкиваюсь с проблемой скручивания пакетов, когда я читаю это. Кажется, мне нужно установить IP_MULTICAST_L OOP в false. Это не легко сделать в Go.

Я нашел этот пост . Кажется, это должно работать. Но я все еще получаю копии с того же хоста. Как это сделать?

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

1 Ответ

0 голосов
/ 04 марта 2020

Самый простой способ - использовать оболочку ListenMulticastUDP в пакете net, как на самом деле уже объяснялось в другом ответе SO, на который вы указываете, Как установить IP_MULTICAST_L OOP в многоадресной рассылке UDPConn в 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)
    }
}
...