Table des matières
Contenu de la question
Solution de contournement
Maison développement back-end Golang La multidiffusion ne fonctionne pas sous Linux dans Golang

La multidiffusion ne fonctionne pas sous Linux dans Golang

Feb 10, 2024 pm 04:42 PM
linux操作系统

多播在 golang 中的 Linux 上不起作用

Éditeur PHP Xinyi, aujourd'hui je veux discuter avec vous du problème que la multidiffusion dans Golang ne fonctionne pas sous Linux. La multidiffusion est une méthode de communication réseau qui transmet des données entre un seul expéditeur et plusieurs récepteurs. Cependant, dans Golang, nous pouvons rencontrer des situations où la multidiffusion ne fonctionne pas sur les systèmes d'exploitation Linux. Cet article explique pourquoi ce problème se produit et propose des solutions possibles. commençons!

Contenu de la question

Ce code envoie et reçoit des paquets multicast.

Ce code fonctionne sous Windows 10 mais pas sous Linux : pourquoi ?

Le contenu packagé (ip 230.0.0.1, port de destination 9001) a été envoyé, mais la multidiffusion n'a pas été reçue par l'application

Packet (ip 230.0.0.2, port de destination 9002).

Quel est le problème ?

Pour tester mon application j'ai utilisé une vm Linux : peut-être, c'est la raison ?

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
}
Copier après la connexion

Solution de contournement

Modifier l'application pour qu'elle écoute sur l'une des adresses IP suivantes la fera fonctionner sous Linux et Macos :

  • L'adresse IP du groupe multicast (rx_multicastaddr dans la question)
  • Adresse générique (0.0.0.0).

Mais il n'est pas clair si cela fonctionnera lorsqu'il écoutera l'adresse IP d'un nic (par exemple 192.168.0.5). D'après mes tests et la description de la question, cela fonctionne sous Windows, mais pas sous Linux ou Macos. Je n'ai pas pu trouver de source faisant autorité décrivant ce comportement.

Vous trouverez ci-dessous une démonstration simplifiée du drapeau d'acceptation.

Sur l'appareil 1, exécutez-le avec la commande suivante (remplacez le nom de l'interface par le nom de votre appareil) :

go run . -listen 230.0.0.1:9001 -join 230.0.0.1:9001 -send 230.0.0.2:9002 -ifname eth0
Copier après la connexion

Sur l'appareil 2, exécutez-le avec la commande suivante (remplacez le nom de l'interface par le nom de l'interface de votre appareil) :

go run . -listen 0.0.0.0:9002 -join 230.0.0.2:9002 -send 230.0.0.1:9001 -ifname ethernet
Copier après la connexion
package main

import (
    "flag"
    "log"
    "net"
    "time"

    "golang.org/x/net/ipv4"
)

var (
    listen string
    join   string
    send   string
    ifname string
)

func main() {
    flag.StringVar(&listen, "listen", "230.0.0.1:9001", "")
    flag.StringVar(&join, "join", "230.0.0.1:9001", "the multicast group address to receive data from")
    flag.StringVar(&send, "send", "230.0.0.2:9002", "the multicast group address to send data to")
    flag.StringVar(&ifname, "ifname", "eth0", "the name of the interface")
    flag.Parse()

    itf, err := net.InterfaceByName(ifname)
    if err != nil {
        panic(err)
    }

    groupAddr, err := net.ResolveUDPAddr("udp4", join)
    if err != nil {
        panic(err)
    }

    c, err := net.ListenPacket("udp4", listen)
    if err != nil {
        panic(err)
    }
    defer c.Close()

    p := ipv4.NewPacketConn(c)
    if err := p.JoinGroup(itf, &net.UDPAddr{IP: groupAddr.IP}); err != nil {
        panic(err)
    }
    log.Printf("join multicast group %s, waiting...", join)

    go sendData(c, send)
    receivedData(p)
}

func sendData(c net.PacketConn, target string) {
    data := []byte(ifname)

    addr, err := net.ResolveUDPAddr("udp4", target)
    if err != nil {
        panic(err)
    }

    for {
        _, err := c.WriteTo(data, addr)
        if err != nil {
            panic(err)
        }
        time.Sleep(time.Second)
    }
}

func receivedData(receiver *ipv4.PacketConn) {
    buf := make([]byte, 1500)
    for {
        n, _, _, err := receiver.ReadFrom(buf)
        if err == nil {
            log.Printf("Receive Data from: %s\n", buf[0:n])
        }
    }
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide complet pour désinstaller le logiciel Kali Linux pour résoudre les problèmes de stabilité du système Guide complet pour désinstaller le logiciel Kali Linux pour résoudre les problèmes de stabilité du système Mar 23, 2024 am 10:50 AM

Cette étude fournit une analyse complète et approfondie des problèmes de désinstallation de logiciels pouvant survenir lors du processus de test d'intrusion et d'audit de sécurité de KaliLinux, et propose des solutions pour garantir la stabilité et la fiabilité du système. 1. Comprendre la méthode d'installation du logiciel Avant de désinstaller le logiciel de Kalilinux, il est crucial de déterminer d'abord son chemin d'installation. Ensuite, la solution de déchargement appropriée est sélectionnée en conséquence sur la base du chemin sélectionné. Les méthodes d'installation courantes incluent apt-get, dpkg, la compilation du code source et d'autres formulaires. Chaque stratégie a ses propres caractéristiques et les mesures de déchargement correspondantes. 2. Utilisez la commande apt-get pour désinstaller le logiciel Dans le système KaliLinux, le composant fonctionnel apt-get est largement utilisé pour exécuter des progiciels de manière efficace et pratique.

Un guide complet d'installation du système d'exploitation domestique Kirin Linux, réalisé en 15 minutes Un guide complet d'installation du système d'exploitation domestique Kirin Linux, réalisé en 15 minutes Mar 21, 2024 pm 02:36 PM

Récemment, le système d'exploitation national Kirin Linux a attiré beaucoup d'attention. En tant qu'ingénieur informatique senior, j'ai un fort intérêt pour l'innovation technologique, j'ai donc personnellement expérimenté le processus d'installation de ce système, et je vais maintenant partager mon expérience avec vous. Avant d'exécuter le processus d'installation, j'étais parfaitement préparé aux étapes pertinentes. La première tâche consiste à télécharger et copier la dernière image du système d'exploitation Kirin Linux sur une clé USB ; deuxièmement, pour Linux 64 bits, à s'assurer que les données importantes des appareils personnels ont été sauvegardées pour faire face aux problèmes d'installation potentiels ; éteignez l’ordinateur et insérez la clé USB. Après avoir accédé à l'interface d'installation et redémarré l'ordinateur, appuyez rapidement sur la touche de fonction F12, entrez dans le menu de démarrage du système et sélectionnez l'option de démarrage prioritaire USB. Avec un écran de démarrage magnifique et simple apparaissant devant vous

disque USB d'installation de Puppylinux disque USB d'installation de Puppylinux Mar 18, 2024 pm 06:31 PM

En fait, après une longue période d'utilisation d'un ordinateur, les performances globales afficheront une tendance à la baisse et l'adaptabilité au système Windows continuera de diminuer. En plus des raisons liées à l'ordinateur lui-même, le système Windows continue d'être amélioré et étendu, et les exigences matérielles sont également de plus en plus élevées. Par conséquent, il n’est pas surprenant que les anciens ordinateurs connaissent un certain retard après l’installation du système Windows. Auparavant, de nombreux amis posaient des questions en arrière-plan sur les retards du système : que faire des vieux ordinateurs ? Si vous constatez que l’installation du nouveau système Windows 10 sur votre ancien ordinateur entraîne des retards et des problèmes de fonctionnement, envisager de passer à Linux peut être un bon choix. Dabaicai a compilé 5 systèmes micro-Linux, adaptés aux anciens ordinateurs et pouvant réduire efficacement l'utilisation du processeur et rendre votre

Comment résoudre le problème des caractères tronqués affichés sur la ligne de commande Linux Comment résoudre le problème des caractères tronqués affichés sur la ligne de commande Linux Mar 21, 2024 am 08:30 AM

Méthodes pour résoudre le problème des caractères tronqués affichés sur la ligne de commande Linux. Dans le système d'exploitation Linux, nous rencontrerons parfois des caractères tronqués affichés lors de l'utilisation de l'interface de ligne de commande, ce qui affectera notre visualisation et notre compréhension normales des résultats ou du fichier de sortie de la commande. Contenu. Les causes des caractères tronqués peuvent être dues à des paramètres de jeu de caractères système incorrects, à un logiciel de terminal ne prenant pas en charge l'affichage de jeux de caractères spécifiques, à des formats d'encodage de fichiers incohérents, etc. Cet article présentera quelques méthodes pour résoudre le problème des caractères tronqués affichés sur la ligne de commande Linux et fournira des exemples de code spécifiques pour aider les lecteurs à résoudre des problèmes similaires.

Une discussion approfondie de la structure de stockage physique du système de fichiers Linux ext2 Une discussion approfondie de la structure de stockage physique du système de fichiers Linux ext2 Mar 14, 2024 pm 09:06 PM

Le système de fichiers Linuxext2 est un système de fichiers utilisé sur la plupart des systèmes d'exploitation Linux. Il utilise une structure de stockage sur disque efficace pour gérer le stockage des fichiers et des répertoires. Avant d'aborder la structure de stockage physique du système de fichiers Linuxext2, nous devons d'abord comprendre quelques concepts de base. Dans le système de fichiers ext2, les données sont stockées dans des blocs de données (blocs), qui sont les plus petites unités allouables dans le système de fichiers. Chaque bloc de données a une taille fixe, généralement 1 Ko, 2 Ko ou 4

Monter automatiquement les disques sous Linux Monter automatiquement les disques sous Linux Mar 20, 2024 am 11:30 AM

Si vous utilisez un système d'exploitation Linux et souhaitez que le système monte automatiquement un lecteur au démarrage, vous pouvez le faire en ajoutant l'identifiant unique (UID) du périphérique et le chemin du point de montage au fichier de configuration fstab. fstab est un fichier de table du système de fichiers situé dans le répertoire /etc. Il contient des informations sur les systèmes de fichiers qui doivent être montés au démarrage du système. En modifiant le fichier fstab, vous pouvez vous assurer que les lecteurs requis sont chargés correctement à chaque démarrage du système, garantissant ainsi un fonctionnement stable du système. Les pilotes à montage automatique peuvent être utilisés facilement dans diverses situations. Par exemple, je prévois de sauvegarder mon système sur un périphérique de stockage externe. Afin de réaliser l'automatisation, assurez-vous que l'appareil reste connecté au système, même au démarrage. De même, de nombreuses applications seront directement

Pourquoi les processus sous Linux dorment-ils ? Pourquoi les processus sous Linux dorment-ils ? Mar 20, 2024 pm 02:09 PM

Pourquoi les processus sous Linux dorment-ils ? Dans le système d'exploitation Linux, un processus peut devenir inactif pour diverses raisons et conditions. Lorsqu'un processus est dans un état dormant, cela signifie qu'il est temporairement suspendu et ne peut pas poursuivre son exécution tant que certaines conditions ne sont pas remplies avant de pouvoir être réveillé pour poursuivre son exécution. Ensuite, nous présenterons en détail plusieurs situations courantes lorsqu'un processus entre en veille prolongée sous Linux et les illustrerons avec des exemples de code spécifiques. En attente de la fin des E/S : lorsqu'un processus lance une opération d'E/S (telle que la lecture

Créer et exécuter des fichiers Linux '.a' Créer et exécuter des fichiers Linux '.a' Mar 20, 2024 pm 04:46 PM

Travailler avec des fichiers dans le système d'exploitation Linux nécessite l'utilisation de diverses commandes et techniques qui permettent aux développeurs de créer et d'exécuter efficacement des fichiers, du code, des programmes, des scripts et d'autres éléments. Dans l'environnement Linux, les fichiers portant l'extension « .a » sont d'une grande importance en tant que bibliothèques statiques. Ces bibliothèques jouent un rôle important dans le développement de logiciels, permettant aux développeurs de gérer et de partager efficacement des fonctionnalités communes sur plusieurs programmes. Pour un développement logiciel efficace dans un environnement Linux, il est crucial de comprendre comment créer et exécuter des fichiers « .a ». Cet article explique comment installer et configurer de manière complète le fichier Linux « .a ». Explorons la définition, l'objectif, la structure et les méthodes de création et d'exécution du fichier Linux « .a ». Qu'est-ce que L

See all articles