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에서 실행됩니다.
rx_multicastaddr
질문에)0.0.0.0
). 그러나 NIC의 IP 주소(예: 192.168.0.5
)를 수신할 때 작동할지는 확실하지 않습니다. 내 테스트와 질문의 설명에 따르면 Windows에서는 작동하지만 Linux 또는 Macos에서는 작동하지 않습니다. 이 동작을 설명하는 권위 있는 소스를 찾을 수 없습니다.
아래는 수락 플래그에 대한 간단한 데모입니다.
장치 1에서 다음 명령을 사용하여 실행합니다(인터페이스 이름을 장치 이름으로 바꿉니다):
으아악장치 2에서 다음 명령을 사용하여 실행합니다(인터페이스 이름을 장치의 인터페이스 이름으로 바꿉니다):
으아악 으아악위 내용은 멀티캐스트가 golang의 Linux에서 작동하지 않습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!