如何将此 TCP/IP MULTICAST 代码从 Python 翻译为 Go

问题描述 投票:0回答:1

我有这段代码,用 Python 编写。据我了解

  • 创建单个套接字
  • 将每个本地 IP 地址添加为给定多播组的成员。

如果任何本地接口收到该组/端口的多播消息,recv 将返回结果。

import sys
import socket
import struct

MULTICASTGROUP = "230.0.0.2"
MULTICASTPORT = 4450

hostname = socket.gethostname()
hosts = socket.gethostbyname_ex(hostname)
hostinterfaceips = hosts[2]

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MULTICASTPORT))
      
for inf in hostinterfaceips:
    sock.setsockopt(
       socket.IPPROTO_IP,
       socket.IP_ADD_MEMBERSHIP,
       socket.inet_aton(MULTICASTGROUP) + socket.inet_aton(inf)
    )

data = sock.recv(1500)
print(data)

如何将此代码改编为 Go?据我所知。我很难理解 net 包,尤其是关于多播

func TestHost(t *testing.T) {
    hostname, err := os.Hostname()
    if err != nil {
        t.Fatal(err)
    }
    fmt.Printf("hostname: %s\n", hostname)
    addrs, err := net.LookupHost(hostname)
    if err != nil {
        t.Fatal(err)
    }
    for i, addr := range addrs {
        fmt.Printf("%d: %s\n", i, addr)
    }
}
python go networking multicast
1个回答
0
投票

事实证明,我的问题源于以下事实:net包默认禁用环回上的多播。您必须使用类似以下代码的内容重新打开它:

func createMulticastConnection(group string, port int) (*net.UDPConn, error) {
    interfaces, err := getActiveInterfaces()
    if err != nil {
        return nil, err
    }
    var iface *net.Interface

    // This grabs the first physical interface with multicast that is up.
    for i := range interfaces {
        if interfaces[i].Flags&net.FlagMulticast != 0 {
            iface = interfaces[i]
            break
        }
    }
    if iface == nil {
        return nil, fmt.Errorf("no valid interface found")
    }
    addr := net.UDPAddr{
        IP:   net.ParseIP(group),
        Port: port,
    }
    conn, err := net.ListenUDP("udp", &addr)
    if err != nil {
        return nil, err
    }

    // This code enables loopback for multicast messages. By default,
    // net disables loopback multicast and this is the only way
    // to turn it back on.
    if addr.IP.To4() != nil {
        pc := ipv4.NewPacketConn(conn)
        if err := pc.JoinGroup(iface, &addr); err != nil {
            return nil, err
        }
        if err := pc.SetMulticastLoopback(true); err != nil {
            return nil, err
        }
    } else if addr.IP.To16() != nil {
        pc := ipv6.NewPacketConn(conn)
        if err := pc.JoinGroup(iface, &addr); err != nil {
            return nil, err
        }
        if err := pc.SetMulticastLoopback(true); err != nil {
            return nil, err
        }
    }
}
// Returns a slice of "valid" addresses, i.e. ones
// that are "up" (whatever that means) and have an
// actual hardware address (meaning they aren't VPN interfaces)
func getActiveInterfaces() ([]*net.Interface, error) {
    interfaces, err := net.Interfaces()
    if err != nil {
        return nil, err
    }
    ret := []*net.Interface{}
    for i := range interfaces {
        if interfaces[i].Flags&net.FlagUp != 0 &&
            interfaces[i].HardwareAddr != nil {
            ret = append(ret, &interfaces[i])
        }
    }
    return ret, nil
}
© www.soinside.com 2019 - 2024. All rights reserved.