2012-02-11 13 views
6

¿Es posible recibir datos de más de un grupo de multidifusión en un solo socket?Suscripción a múltiples grupos de multidifusión en un socket (Linux, C)

Por ejemplo:

void AddGroup(int sock, 
       const char* mc_addr_str, 
       int mc_port, 
       const char* interface) { 
    struct sockaddr_in mc_addr; 
    memset(&mc_addr, 0, sizeof(mc_addr)); 
    mc_addr.sin_family  = AF_INET; 
    mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str); 
    mc_addr.sin_port  = htons(mc_port); 

    if ((bind(sock, (struct sockaddr *) &mc_addr, 
      sizeof(mc_addr))) < 0) { 
    perror("bind() failed"); 
    exit(1); 
    } 

    // construct an IGMP join request structure 
    struct ip_mreq mc_req; 
    mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str); 
    mc_req.imr_interface.s_addr = inet_addr(interface); 

    if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
        (void*) &mc_req, sizeof(mc_req))) < 0) { 
    perror("setsockopt() failed"); 
    exit(1); 
    } 
} 

Este código funciona cuando agrego un grupo de multidifusión. Pero cuando trato de agregar otro, falla el "enlace". No entiendo por qué el enlace debe estar allí en primer lugar. (pero el código no funciona sin él).

Idealmente me gustaría llamar a AddGroup varias veces en el mismo socket. es posible? ¿O necesito un conector por grupo y luego solo uso sondeo?

Respuesta

3

Solo enlaza un socket una vez. Omita el enlace la segunda vez y vea qué pasa.

-3

No creo que sea posible unir más de un grupo de multidifusión en un socket dado. El socket está definido por el emparejamiento de la fuente ip/port y destination ip/port. El sistema operativo no sabría qué hacer con los datos que provienen de la segunda ip/puerto porque no tendría un socket para enviarlos.

El enlace es necesario para registrar la conexión con el sistema operativo. Básicamente es como registrar un identificador de archivo.

La mejor manera de hacerlo sería crear un socket para cada grupo de multidifusión y luego llamar a select(). select() le informará si algún socket tiene datos listos para leer.

Revise sus páginas man para obtener más información sobre socket(), bind() y seleccione().

+2

Usted es incorrecta. Puedes unirte a tantos grupos como quieras. Unirse a grupos de multidifusión no tiene nada que ver con la tupla de identificación. – EJP

6

Puede unir tantos grupos de multidifusión como quiera, utilizando la llamada setsockopt() apropiada con la opción IP_ADD_MEMBERSHIP, en lugar de bind().

+0

Cuando elimino el "enlace" en las llamadas subsiguientes a AddGroup, solo el primer grupo de multidifusión parece estar "suscrito" a. – Switch

+0

@Switch Si no se puede acceder a un grupo a través de su ruta IP predeterminada, debe especificar la dirección local de salida apropiada al unirse al grupo, por lo que el mensaje IGMP de "agregar miembro" va en la dirección adecuada. – EJP

2

bind a la dirección pasiva, es decir, 0.0.0.0 para IPv4 y usa ASM o SSM para incorporar grupos adicionales, p. IP_ADD_MEMBERSHIP según la lista.

Solo puede bind una vez.

2

Puede unir tantos grupos de multidifusión que desee en un solo socket. Consulte setsockopt(), IP_PKTINFO para conocer de qué grupo de multidifusión está leyendo datos.

0

Sí, es posible: Buscar en el ejemplo, en el enlace (http://www.tenouk.com/Module41c.html) Para acortar esto en unos pocos pasos:

  1. Usted setsockopt con SO_REUSEADDR
  2. que ates en la INADDR_ANY
  3. Usted setsockopt con IP_ADD_MEMBERSHIP en cada grupo del que quieras recibir datagram.
  4. Me parece que el uso de IP_PKTINFO da una opción para distinguir los paquetes recibidos, pero remitente debe tener cuidado acerca de su preparación (Setting the source IP for a UDP socket)
Cuestiones relacionadas