Networking 如何使用golang在Internet上实现多播?

Networking 如何使用golang在Internet上实现多播?,networking,go,network-programming,multicast,Networking,Go,Network Programming,Multicast,我是golang programming和multicast programming的新手。我在年看过一个关于golang multicast的节目 我在大学实验室局域网的几台计算机上运行了该代码。一台计算机运行函数ping发送多播数据包,其他计算机运行函数servemulticastup接收多播数据包。它成功了。 但是,当我在一台计算机上运行函数ping,在Internet上的另一台计算机上运行函数servemulticastup(两台计算机不在LAN中)时,它无法接收数据。接收器具有NAT,

我是golang programming和multicast programming的新手。我在年看过一个关于golang multicast的节目

我在大学实验室局域网的几台计算机上运行了该代码。一台计算机运行函数ping发送多播数据包,其他计算机运行函数servemulticastup接收多播数据包。它成功了。 但是,当我在一台计算机上运行函数ping,在Internet上的另一台计算机上运行函数servemulticastup(两台计算机不在LAN中)时,它无法接收数据。接收器具有NAT,并且没有公共IP地址

我看到一些人的回答是Internet不支持多播,但我知道VOIP是多播技术的一个例子,我们可以在Internet上实现多播

那么,接收方无法接收数据包的原因是什么?我应该如何修改代码以实现Internet上的多播?

多播路由与单播路由有很大不同。多播是广播的一种形式,通常不跨路由器。您可以启用多播路由,但必须在路径中的所有路由器上启用多播路由(使用相同的多播路由类型),而这在公共Internet上是不可能发生的。公共互联网将从密集模式多播崩溃,没有ISP将资源专用于稀疏模式

我不知道你为什么认为VoIP使用多播(它没有)

如果您希望通过公共Internet从一个站点多播到另一个站点,则必须使用支持多播的隧道,例如GRE。这会将您的多播数据包包装在单播数据包中,以跨公共Internet。您仍然必须在每一侧配置路由器以支持多播路由。

多播路由与单播路由有很大不同。多播是广播的一种形式,通常不跨路由器。您可以启用多播路由,但必须在路径中的所有路由器上启用多播路由(使用相同的多播路由类型),而这在公共Internet上是不可能发生的。公共互联网将从密集模式多播崩溃,没有ISP将资源专用于稀疏模式

我不知道你为什么认为VoIP使用多播(它没有)

如果您希望通过公共Internet从一个站点多播到另一个站点,则必须使用支持多播的隧道,例如GRE。这会将您的多播数据包包装在单播数据包中,以跨公共Internet。您仍然必须在每一侧配置路由器以支持多播路由

import (
    "encoding/hex"
    "log"
    "net"
    "time"
)

const (
    srvAddr         = "224.0.0.1:9999"
    maxDatagramSize = 8192
)

//send multicast data
func ping(a string) {
    addr, err := net.ResolveUDPAddr("udp", a)
    if err != nil {
        log.Fatal(err)
    }
    c, err := net.DialUDP("udp", nil, addr)
    for {
        c.Write([]byte("hello, world\n"))
        time.Sleep(1 * time.Second)
    }
}

//print received data
func msgHandler(src *net.UDPAddr, n int, b []byte) {
    log.Println(n, "bytes read from", src)
    log.Println(hex.Dump(b[:n]))
}

//join multicast group and receive multicast data
func serveMulticastUDP(a string, h func(*net.UDPAddr, int, []byte)) {
    addr, err := net.ResolveUDPAddr("udp", a)
    if err != nil {
        log.Fatal(err)
    }
    l, err := net.ListenMulticastUDP("udp", nil, addr)
    l.SetReadBuffer(maxDatagramSize)
    for {
        b := make([]byte, maxDatagramSize)
        n, src, err := l.ReadFromUDP(b)
        if err != nil {
            log.Fatal("ReadFromUDP failed:", err)
        }
        h(src, n, b)
    }
}