Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2613 connectés 

  FORUM HardWare.fr
  Programmation
  C

  multicast et linux

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

multicast et linux

n°2194742
xilebo
noone
Posté le 18-06-2013 à 15:49:14  profilanswer
 

Bonjour,
 
J'ai un petit souci lors d'envoi de trame multicast sous linux. Voici un code exemple pour illustrer le problème :
 

Code :
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <sys/types.h>
  4. #include <string.h>
  5. #include <netinet/in.h>
  6. #include <netinet/ip.h>
  7. #include <errno.h>
  8. #include <arpa/inet.h>
  9. static const char multicast_group_sz[] = "224.1.2.3";
  10. static const short port = 65007;
  11. int main()
  12. {
  13. int sock = socket( AF_INET , SOCK_DGRAM , IPPROTO_UDP );
  14. unsigned long hote_l = inet_addr( multicast_group_sz );
  15. struct sockaddr_in addr;
  16. int ret;
  17. memset( &addr , 0 , sizeof(addr ));
  18. addr.sin_family = AF_INET;
  19. addr.sin_addr.s_addr = hote_l;
  20. addr.sin_port = htons( port );
  21. struct in_addr iface_addr;
  22. iface_addr.s_addr = inet_addr("172.17.17.17" );
  23. ret = setsockopt( sock , IPPROTO_IP , IP_MULTICAST_IF , (char *)&iface_addr , sizeof ( iface_addr ) );
  24. if ( ret < 0 )
  25. {
  26.  printf("Error setsockopt %d\n", errno );
  27. }
  28. while ( 1 )
  29. {
  30.  char buffer[1024];
  31.  fgets( buffer,  1024 , stdin );
  32.  int len = strlen( buffer);
  33.  buffer[len - 1] = 0; // virer le \n et remplacer par un fin de chaine
  34.  ret = sendto( sock , buffer , len , 0 ,(struct sockaddr *) &addr, sizeof ( addr ) );
  35.  printf("sendto : %d %d\n" , ret , errno );
  36.  if ( strcmp( buffer , "QUIT" ) == 0 )
  37.  {
  38.   break;
  39.  }
  40. }
  41. close ( sock );
  42. return 0;
  43. }


 
si je commente les lignes  

Code :
  1. struct in_addr iface_addr;
  2. iface_addr.s_addr = inet_addr("172.17.17.17" );
  3. ret = setsockopt( sock , IPPROTO_IP , IP_MULTICAST_IF , (char *)&iface_addr , sizeof ( iface_addr ) );


 
mon sendto renvoie une erreur. On va dire que c'est normal, je ne peux pas envoyer en multicast sur une socket, si je ne lui ai pas précisé préalablement qu'elle doit fonctionner en multicast.
 
 
Si maintenant je remplace ces mêmes lignes par :  

Code :
  1. struct in_addr iface_addr;
  2. iface_addr.s_addr = INADDR_ANY;
  3. ret = setsockopt( sock , IPPROTO_IP , IP_MULTICAST_IF , (char *)&iface_addr , sizeof ( iface_addr ) );


 
setsockopt ne me retourne pas d'erreur ( donc on peut suppose que ca s'est bien passé ) , par contre mon sendto me renvoie également une erreur ( network unreachable me semble-t-il ).
 
Si maintenant je mets  

Code :
  1. struct in_addr iface_addr;
  2. iface_addr.s_addr = inet_addr("172.17.17.17" );
  3. ret = setsockopt( sock , IPPROTO_IP , IP_MULTICAST_IF , (char *)&iface_addr , sizeof ( iface_addr ) );


 
Comme dans le code exemple, ici 172.17.17.17 étant l'adresse IP de l'interface sur laquelle je veux dialoguer ( eth0 ) , mon sendto fonctionne bien et je vois bien le paquet UDP partir avec wireshark.
 
 
Ma question est : pourquoi cela ne marche pas si je fais un setsockopt sur INADDR_ANY, y a-t-il une option supplémentaire pour autoriser ce genre de chose ?
 
Je précise que sous windows, ce code fonctionne bien, et c'est un besoin que j'ai car je ne connais pas forcément l'adresse IP de l'interface sur laquelle je veux dialoguer.
 
Merci d'avance  :jap:

mood
Publicité
Posté le 18-06-2013 à 15:49:14  profilanswer
 

n°2194751
Farian
Posté le 18-06-2013 à 16:07:55  profilanswer
 

Bonjour ! Avez-vous défini une route pour le multicast ?

Code :
  1. route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 (en tant que root)


Si oui, il ne doit pas être nécessaire de dire quelle interface utiliser dans le programme, dans le cas contraire, il parait logique d'indiquer au système sur quelle interface réseau (eth0, lo) envoyer les trames.
 
De mémoire, sous Windows il n'est pas nécessaire d'ajouter cette route pour que cela marche (est-elle ajoutée automatiquement ?), ce qui explique la différence de fonctionnement, que j'ai en effet souvent remarquée entre les deux OS.
 
Bonne continuation !
 
PS : Avec la gestion des routes, vous pouvez diriger finement vos trames multicast vers l'une ou l'autre de vos interfaces, en faisant varier l'IP et le masque.

n°2194755
xilebo
noone
Posté le 18-06-2013 à 16:14:58  profilanswer
 

super, c'est exactement ca le probleme.
 
Sous windows, les routes multicast sont définies pour toutes les interfaces par défaut, donc si je fais un send sous windows, il envoie mon paquet sur toutes les interfaces.
 
Sous linux, par défaut, aucune route n'est définie, donc si je ne précise pas l'interface, il ne sait pas où aller ( même si je n'ai qu'une interface réseau ). En ajoutant la route comme tu le précises, cela fonctionne.
 
 
Je viens de tester, ca marche. Merci pour l'info.
 
 

n°2194756
xilebo
noone
Posté le 18-06-2013 à 16:18:08  profilanswer
 

J'en profite pour glisser une info supplémentaire, sur la réception cette fois-ci.
 
Le setsockopt ( ... IP_ADD_MEMBERSHIP ... ) doit se faire AVANT le bind sous linux, alors que sous windows , il faut le faire APRES le bind.
 
Je n'ai pas d'explication  à propos de cette différence d'implémentation.
 
 
 
next step  : ios  :jap:

n°2194762
Farian
Posté le 18-06-2013 à 16:59:33  profilanswer
 

xilebo a écrit :

... ( même si je n'ai qu'une interface réseau ) ...


 
Justement, il y a deux interfaces sous Linux : "eth0" et la boucle locale "lo", d'où, sans doute, la confusion du système (je n'ai jamais essayé d'en désactiver une voir si cela marchait sur la seule restante).


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  multicast et linux

 

Sujets relatifs
installation activate perl version 5.16 sous linuxcomment faire cohabiter gettext sur windows et linux
utilisation de select() / fd_set() et autres joyeusetés sous linuxComment créer un dossier avec des espaces en Java sous Linux ?
relation entre script bat et linuxInterpréter une séquence d'échappement sur Gnu/Linux
[PHP/Linux] Shell_exec[Résolu] [GNU/Linux] Redirection temporaire de la sortie standard
Sous Linux, logger un script shell[RESOLU] socket inter-process C/PHP linux
Plus de sujets relatifs à : multicast et linux


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR