2013-04-15 7 views
9

Desidero inviare pacchetti multicast UDP all'indirizzo di loopback e ricevere lo stesso in altre applicazioni. Tutti i test eseguiti su fedora core 17 Linux.Multicasting sul dispositivo di loopback

L'idea è di ricevere un flusso video tramite RTSP/HTTP o qualsiasi altro protocollo di rete e di eseguirne il multicast sull'indirizzo di loopback in modo da poter utilizzare VLC per riprodurre il flusso utilizzando l'indirizzo multicast. Tralasciando altri bitrate e problemi multicast controllati, ho provato a leggere un file video e multicast sul dispositivo loopback. Ma quando ho provato a giocare lo stesso su vlc, non ha funzionato. Sono in grado di vedere pacchetto sempre trasmessa in wireshark ma l'ip src è tratto dalla mia interfaccia di rete predefinita (cioè l'interfaccia che è il mio gateway predefinito)

Ho già provato i seguenti comandi

sudo ifconfig lo multicast sudo ip route add 239.252.10.10 dev lo

Qualsiasi suggerimento a riguardo sarebbe molto utile.

codice del programma di test incollato sotto

  #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <arpa/inet.h> 
    #include <netinet/in.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <unistd.h> 


    #define MULTICAST_ADDRESS "239.252.10.10" 
    #define UDP_PORT 1234 
    #define INTERFACE_IP "127.0.0.1" 
    #define MTU 1474 
    #define DATA_BUFFER_SIZE (1024*1024) 

    static int socket_init(char *intf_ip) { 
    int sd; 
    struct in_addr localInterface; 

     sd = socket (AF_INET, SOCK_DGRAM, 0); 
     if (sd < 0) { 
      perror ("Opening datagram socket error"); 
      return -1; 
     } 
     else 
     printf ("Opening the datagram socket...OK.\n"); 

     localInterface.s_addr = inet_addr (intf_ip); 

     if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char *) &localInterface,sizeof (localInterface)) < 0){ 
      perror ("Setting local interface error"); 
      close(sd); 
      return -1; 
     } 
     else 
     printf ("Setting the local interface...OK\n"); 
    #if 1 
     char loopch = 1; 

     if(setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0){ 
     perror("Setting IP_MULTICAST_LOOP error"); 
     close(sd); 
     return -1; 
     } 
     else 
     printf("Enabling the loopback...OK.\n"); 
    #endif 
     return sd; 

    } 


    static int transmit_packet(int sd, char *databuf, int size,char *ip, unsigned short port){ 

    struct sockaddr_in groupSock; 
    int len,datalen,rc; 

     memset ((char *) &groupSock, 0, sizeof (groupSock)); 

     groupSock.sin_family = AF_INET; 

     groupSock.sin_addr.s_addr = inet_addr (ip); 

     groupSock.sin_port = htons (port); 

     len=0; 
     datalen = MTU; 
     if(size < MTU) 
     datalen = size; 

     while(len < size){ 
     rc = sendto(sd, databuf, datalen, 0, (struct sockaddr *) &groupSock,sizeof (groupSock)); 
     if(rc <0){ 
      perror ("Sending datagram message error"); 
      return -1; 
     } 
     usleep(10000); 
     len += rc; 
     } 
     return len; 
    } 

    static int transmit_file(char *filepath, char *dstip, char *srcip,unsigned short port) { 
    FILE *fp; 
    int sd,rc; 
    char *databuf; 


     fp = fopen(filepath, "r"); 
     if(!fp) { 
     printf("transmit_file : no such file or directory %s \n",filepath); 
     return -1; 
     } 
     sd = socket_init(srcip); 
     if(sd < 0) { 
     printf("Socket initialization failed \n"); 
     fclose(fp); 
     return -1; 
     } 
     databuf = (char*) malloc(sizeof(char)*DATA_BUFFER_SIZE); 
     if(!databuf) { 
     printf("Unable to allocate databuf\n"); 
     close(sd);fclose(fp); 
     return -1; 
     } 
     while(!feof(fp)){ 
     rc = fread(databuf,1,DATA_BUFFER_SIZE,fp); 
     if(rc<= 0) { 
      printf("read failed or EOF reached\n"); 
      break; 
     }   
     if(transmit_packet(sd,databuf,rc,dstip,port) <0) 
      printf("Transmit failed\n");  
     } 
     close(sd);fclose(fp); 
     free(databuf); 
     return 0; 
    } 

    int main(int argc, char *argv[]){ 

     if(argc != 3){ 
     printf("%s <filename> <ip>\n",argv[0]); 
     return -1; 
     } 
     transmit_file(argv[1],argv[2],INTERFACE_IP,UDP_PORT); 
     return 0; 
    } 
+0

hai avuto qualche soluzione ?? ho anche lo stesso problema. – user2990252

risposta

0

desidero inviare i pacchetti UDP multicast per loopback indirizzo

fermata proprio lì. Non puoi farlo. È impossibile. È possibile inviare solo i multicast agli indirizzi multicast. Il tuo codice non esegue alcun multicasting, semplicemente inviando a 127.0.0.1.

Se si invia solo all'host locale, perché si utilizza il multicast? Hai più processi di ascolto?

l'ip src è tratto dalla mia interfaccia di rete predefinita (cioè l'interfaccia che è il mio gateway predefinito)

Molto probabilmente, come non avete legato la vostra presa. Cosa ti aspettavi?

+0

L'indirizzo multicast può essere fornito dalla riga di comando che viene considerata come ip di destinazione. In pratica, voglio trasmettere tutto ciò che ricevo all'interfaccia di loopback in modo multicast in modo che una applicazione possa riceverlo per registrare in un file mentre un'altra applicazione lo riproduce e così via. Ecco perché la destinazione multicast è impostata per l'ip di destinazione del pacchetto udp. –

+0

Per l'interfaccia src ip anche se collego il socket a 127.0.0.1 ancora non lo accetta nei pacchetti in uscita. –

+2

@EJP Cosa succede se voglio che più processi vengano letti da uno stream in un modo sub/pub? Video dal vivo per esempio. – Aron

13

È possibile utilizzare multicast su loopback ma è necessario aggiungere un nuovo percorso perché il sistema operativo utilizza l'interfaccia esterna predefinita per impostazione predefinita per multicast. Anche il multicast può essere disabilitato di default su loopback. Su linux puoi cambiarlo con questo comando:

route add -net 224.0.0.0 netmask 240.0.0.0 dev lo 
ifconfig lo multicast