php エディタの Xinyi さん、今日お話したいのは、golang のマルチキャストが Linux 上で動作しないという問題です。マルチキャストは、単一の送信者と複数の受信者の間でデータを送信するネットワーク通信の方法です。ただし、golang では、Linux オペレーティング システムでマルチキャストが機能しない状況に遭遇することがあります。この記事では、この問題が発生する理由と考えられる解決策を説明します。はじめましょう!
このコードはマルチキャストパケットを送受信します。
このコードは Windows 10 では動作しますが、Linux では動作しません。なぜですか?
パッケージ化されたコンテンツ (IP 230.0.0.1、宛先ポート 9001) が送信されましたが、マルチキャストはアプリケーションによって受信されませんでした
パケット (ip 230.0.0.2、宛先ポート 9002)。
###何が問題ですか?アプリケーションをテストするために、Linux VM を使用しました。おそらく、それが理由でしょうか?
package main import ( "net" "os" "strconv" "time" "github.com/rs/zerolog" "golang.org/x/net/ipv4" ) const device1_tx_multicastAddr = "230.0.0.1" const device1_tx_udp_port = 9001 const device2_tx_multicastAddr = "230.0.0.2" const device2_tx_udp_port = 9002 const packetTxDelayMs = 1000 // const ethName = "Ethernet" // Windows const ethName = "eth0" // Linux const modeDevice2 = false // Device 1 //const modeDevice2 = true // Device 2 var logConsole zerolog.Logger func main() { logConsole = zerolog.New(os.Stderr).With().Timestamp(). Str("module", "main"). Logger().Output(zerolog.ConsoleWriter{Out: os.Stderr}). Level(zerolog.InfoLevel) // ********************************** // Initialize Tx localInterface := getInterfaceByName(ethName) logConsole.Info().Str("func", "main").Msg("localInterface: " + ethName) tx_multicastAddr := device1_tx_multicastAddr rx_multicastAddr := device2_tx_multicastAddr tx_udp_port := device1_tx_udp_port rx_udp_port := device2_tx_udp_port if modeDevice2 { tx_multicastAddr = device2_tx_multicastAddr rx_multicastAddr = device1_tx_multicastAddr tx_udp_port = device2_tx_udp_port rx_udp_port = device1_tx_udp_port } logConsole.Info().Str("func", "main").Msg("Open Tx UDP port " + tx_multicastAddr + ":" + strconv.Itoa(tx_udp_port) + "...") remoteDeviceUdpAddr, err := net.ResolveUDPAddr("udp4", tx_multicastAddr+":"+strconv.Itoa(tx_udp_port)) if err != nil { panic(err) } localDeviceUdpAddr, err2 := net.ResolveUDPAddr("udp4", localInterface.String()+":"+strconv.Itoa(rx_udp_port)) if err2 != nil { panic(err2) } logConsole.Info().Str("func", "main").Msg("Listen UDP: " + localDeviceUdpAddr.String() + "...") localDevice, err2 := net.ListenUDP("udp4", localDeviceUdpAddr) if err2 != nil { panic(err2) } // ********************************** // Initialize Rx udpReceiver := ipv4.NewPacketConn(localDevice) ief, errInterface := net.InterfaceByName(ethName) if errInterface != nil { localDevice.Close() panic(errInterface) } logConsole.Info().Str("func", "main").Msg("Join Multicast: " + rx_multicastAddr + "...") err = udpReceiver.JoinGroup(ief, &net.UDPAddr{IP: net.ParseIP(rx_multicastAddr)}) if err != nil { localDevice.Close() panic(err) } // ********************************** // Run Rx/Tx tasks go sendData(localDevice, remoteDeviceUdpAddr, packetTxDelayMs) receivedData(udpReceiver) } // ************************************************* func sendData(localDevice *net.UDPConn, remoteDeviceUdpAddr *net.UDPAddr, packetDelay uint) { data := []byte("1234567890") for { //logConsole.Info().Str("func", "sendData").Msg("Send...") _, err := localDevice.WriteTo(data, remoteDeviceUdpAddr) if err != nil { panic(err) } time.Sleep(time.Duration(packetDelay) * time.Millisecond) } } func receivedData(receiver *ipv4.PacketConn) { buf := make([]byte, 1500) for { n, _, _, err := receiver.ReadFrom(buf) if err == nil { logConsole.Info().Str("func", "receivedData").Msg("Receive Data: " + string(buf[0:n])) } } } // ************************************************* func getInterfaceByName(name string) net.IP { ief, err := net.InterfaceByName(name) if err != nil { panic(err) } addrs, err := ief.Addrs() if err != nil { panic(err) } var ipAddr net.IP for _, addr := range addrs { ipAddr = addr.(*net.IPNet).IP.To4() if ipAddr != nil { break } } if ipAddr == nil { panic("ipAddr is nil") } return ipAddr }回避策次のいずれかの IP アドレスでリッスンするようにアプリケーションを変更すると、Linux および MacOS で実行できるようになります:
)
)。
192.168.0.5) をリッスンするときに機能するかどうかは不明です。私のテストと質問の説明に基づくと、Windowsでは動作しますが、LinuxやMacOSでは動作しません。この動作を説明している信頼できる情報源を見つけることができませんでした。
デバイス 1 で、次のコマンドを使用して実行します (インターフェイス名をデバイスの名前に置き換えます):
リーリー
デバイス 2 で、次のコマンドを使用して実行します (インターフェイス名をデバイスのインターフェイス名に置き換えます):リーリー リーリー
以上がLinuxのgolangでマルチキャストが機能しないの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。