web-dev-qa-db-fra.com

Qu'est-ce que cela signifie de lier un socket multicast (UDP)?

J'utilise UDP multicast entre des hôtes dotés de plusieurs interfaces réseau. J'utilise boost :: asio et je suis dérouté par les 2 opérations que les destinataires doivent effectuer: bind, puis join-group.

Pourquoi avez-vous besoin de spécifier l'adresse locale d'une interface, pendant la liaison, lorsque vous le faites avec chaque groupe de multidiffusion que vous rejoignez?

La question jumelle concerne le port de multidiffusion: Comme vous envoyez un message à une adresse de multidiffusion lors de l’envoi, vous indiquez uniquement lors de l’abonnement à un groupe de multidiffusion l’adresse, pas le port - le port spécifié dans l’appel à confusion lier.

Remarque: "join-group" est un wrapper over setsockopt(IP_ADD_MEMBERSHIP), qui, comme documenté, peut être appelé plusieurs fois sur le même socket pour s'abonner à différents groupes (sur différents réseaux?). Il serait donc parfaitement logique de laisser tomber l'appel de liaison et de spécifier le port chaque fois que je m'abonne à un groupe.

D'après ce que je vois, toujours lié à "0.0.0.0" et en spécifiant l'adresse de l'interface lors de l'adhésion au groupe, fonctionne très bien. Confus.

64
haelix

Lier un socket UDP lors de la réception d'une multidiffusion signifie spécifier une adresse et un port depuis lesquels recevoir des données (PAS une interface locale, comme c'est le cas pour TCP accepteur). L'adresse spécifiée dans cette case a un rôle filtrage, c’est-à-dire que le socket ne recevra que les datagrammes envoyés à cette adresse de multidiffusion et à ce port, quels que soient les groupes joints par la suite par la socket. ) J'ai reçu des datagrammes envoyés à mon groupe de multidiffusion, alors que lors de la liaison avec l'une des interfaces locales, je n'ai rien reçu, même si les datagrammes étaient envoyés sur le réseau auquel cette interface correspondait.

Citation de UNIX® Network Programming Volume 1, Troisième édition: L'API Sockets Networking par W.R Stevens. 21.10. Envoi et réception

[...] Nous voulons que le socket de réception lie le groupe de multidiffusion et le port, par exemple le port 8888 à 239.255.1.2. tous les autres datagrammes susceptibles d’arriver destinés au port 8888.) Nous voulons ensuite que le socket récepteur rejoigne le groupe de multidiffusion. Le socket qui envoie envoie des datagrammes à cette même adresse de multidiffusion et à ce même port, par exemple le port 8888 de 239.255.1.2.

54
haelix

L’opération "bind" consiste essentiellement à "utiliser ce port UDP local pour l’envoi et la réception de données. En d’autres termes, elle attribue ce port UDP à une utilisation exclusive pour votre application. (La même chose vaut pour TCP sockets ).

Lorsque vous vous liez à "0.0.0.0" ( INADDR_ANY ), vous indiquez à la couche TCP/IP d'utiliser tous les adaptateurs disponibles. pour écouter et choisir le meilleur adaptateur pour l'envoi. C'est la pratique standard pour la plupart des codes de socket. La seule fois où vous ne spécifiez pas 0 pour l'adresse IP, c'est quand vous voulez envoyer/recevoir sur une carte réseau spécifique.

De même, si vous spécifiez une valeur de port de 0 lors de la liaison, le système d'exploitation attribue un numéro de port disponible de manière aléatoire à ce socket. Par conséquent, je pense que pour la multidiffusion UDP, vous vous connectez à INADDR_ANY sur un numéro de port spécifique où le trafic de multidiffusion doit être envoyé.

L’opération "rejoindre le groupe de multidiffusion" (IP_ADD_MEMBERSHIP) Est nécessaire car elle indique en principe à votre adaptateur réseau d’écouter non seulement les trames Ethernet lorsque l’adresse MAC de destination est la vôtre, mais également de préciser l’adaptateur Ethernet [~ # ~] nic [~ # ~] ) pour écouter le trafic de multidiffusion IP ainsi que l'adresse Ethernet de multidiffusion correspondante. Chaque adresse IP multidiffusion est mappée sur une adresse Ethernet multidiffusion. Lorsque vous utilisez un socket pour envoyer à une adresse IP multicast spécifique, l'adresse MAC de destination sur la trame Ethernet est définie sur l'adresse MAC multicast correspondante pour l'IP multicast. Lorsque vous rejoignez un groupe de multidiffusion, vous configurez le NIC pour écouter le trafic envoyé à cette même adresse MAC (en plus de la sienne).

Sans le support matériel, la multidiffusion ne serait pas plus efficace que les messages IP en clair. L’opération de jointure demande également à votre routeur/passerelle de transférer le trafic multidiffusion d’autres réseaux. (Quelqu'un se souvient de MBONE?)

Si vous rejoignez un groupe de multidiffusion, tout le trafic de multidiffusion de tous les ports de cette adresse IP sera reçu par la carte réseau. Seul le trafic destiné à votre port d'écoute lié sera transmis à votre application par la pile TCP/IP. En ce qui concerne la raison pour laquelle les ports sont spécifiés lors d’un abonnement multicast - c’est parce que l’IP multicast n’est que cela - IP uniquement. "ports" sont une propriété des protocoles supérieurs (UDP et TCP).

Pour en savoir plus sur la correspondance entre les adresses IP de multidiffusion et les adresses Ethernet de multidiffusion sur divers sites. L'article de Wikipedia est à peu près aussi bon qu'il obtient:

L'IANA est propriétaire de l'adresse MAC OUI 01: 00: 5e. Par conséquent, les paquets multidiffusion sont livrés en utilisant la plage d'adresses Ethernet MAC 01: 00: 5e: 00: 00: 00: 00: 00: 5e: 7f: ff: ff. C'est 23 bits d'espace d'adressage disponible. Le premier octet (01) inclut le bit broadcast/multicast. Les 23 bits inférieurs de l'adresse IP de multidiffusion à 28 bits sont mappés dans les 23 bits d'espace d'adressage Ethernet disponible.

47
selbie

Correction pour Que signifie lier une socket multicast (udp)? tant que cela est partiellement vrai dans la citation suivante:

L’opération "bind" dit en gros "utilisez ce port UDP local pour envoyer et recevoir des données. En d’autres termes, il alloue ce port UDP pour exclusif utilisez pour votre application

Il y a une exception. Plusieurs applications peuvent partager le même port d'écoute (généralement, elles ont une valeur pratique pour les datagrammes de multidiffusion), si le SO_REUSEADDR option appliquée. Par exemple

int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create UDP socket somehow
...
int set_option_on = 1;
// it is important to do "reuse address" before bind, not after
int res = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on, 
    sizeof(set_option_on));
res = bind(sock, src_addr, len);

Si plusieurs processus ont fait cette "liaison de réutilisation", alors chaque datagramme UDP reçu sur ce port partagé sera remis à chacun des processus (fournissant une connexion naturelle avec un trafic multidiffusions).

Voici d'autres détails concernant ce qui se passe dans quelques cas:

  1. toute tentative de liaison ("exclusive" ou "réutilisation") pour libérer le port sera couronnée de succès

  2. la tentative de "liaison exclusive" échouera si le port est déjà "lié à la réutilisation"

  3. la tentative de "réutilisation des liaisons" échouera si un processus conserve la "liaison exclusive"

10
Yury Schkatula

Il est également très important de distinguer un socket multicast SENDING d’un socket multicast RECEIVING.

Je suis d'accord avec toutes les réponses ci-dessus concernant la réception de prises multidiffusion. L'OP a noté que la liaison d'une prise RECEIVING à une interface n'a pas aidé. Cependant, il est nécessaire de lier un socket SENDING multicast à une interface.

Pour un socket multicast SENDING sur un serveur multi-hébergé, il est très important de créer un socket distinct pour chaque interface à laquelle vous souhaitez envoyer. Un socket SENDING lié doit être créé pour chaque interface.

  // This is a fix for that bug that causes Servers to pop offline/online.
  // Servers will intermittently pop offline/online for 10 seconds or so.
  // The bug only happens if the machine had a DHCP gateway, and the gateway is no longer accessible.
  // After several minutes, the route to the DHCP gateway may timeout, at which
  // point the pingponging stops.
  // You need 3 machines, Client machine, server A, and server B
  // Client has both ethernets connected, and both ethernets receiving CITP pings (machine A pinging to en0, machine B pinging to en1)
  // Now turn off the ping from machine B (en1), but leave the network connected.
  // You will notice that the machine transmitting on the interface with
  // the DHCP gateway will fail sendto() with errno 'No route to Host'
  if ( theErr == 0 )
  {
     // inspired by 'ping -b' option in man page:      
     //      -b boundif
     //             Bind the socket to interface boundif for sending.
     struct sockaddr_in bindInterfaceAddr;
     bzero(&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     bindInterfaceAddr.sin_len = sizeof(bindInterfaceAddr);
     bindInterfaceAddr.sin_family = AF_INET;
     bindInterfaceAddr.sin_addr.s_addr = htonl(interfaceipaddr);
     bindInterfaceAddr.sin_port = 0; // Allow the kernel to choose a random port number by passing in 0 for the port.
     theErr = bind(mSendSocketID, (struct sockaddr *)&bindInterfaceAddr, sizeof(bindInterfaceAddr));
     struct sockaddr_in serverAddress;
     int namelen = sizeof(serverAddress);  
     if (getsockname(mSendSocketID, (struct sockaddr *)&serverAddress, (socklen_t *)&namelen) < 0) {
        DLogErr(@"ERROR Publishing service... getsockname err");
     }
     else
     {
        DLog( @"socket %d bind, %@ port %d", mSendSocketID, [NSString stringFromIPAddress:htonl(serverAddress.sin_addr.s_addr)], htons(serverAddress.sin_port) );
     }

Sans ce correctif, l'envoi par multidiffusion obtiendra de manière intermittente sendto () errno 'No route to Host'. Si quelqu'un peut expliquer pourquoi le débranchement d'une passerelle DHCP entraîne la confusion des connecteurs multidiffusion SEND SEND de Mac OS X, j'aimerais l'entendre.

5
Keith Knauber