2013-04-15 25 views
9

Chcę wysłać pakiety multiemisji UDP do adresu sprzężenia zwrotnego i odebrać to samo w innej aplikacji. Wszystkie testy wykonane na rdzeniu Fedory 17 Linux.Rozsyłanie grupowe na urządzeniu z pętlą zwrotną

Chodzi o to, aby otrzymać strumień wideo przez RTSP/HTTP lub jakikolwiek inny protokół sieciowy i przeprowadzić multiemisję na adres sprzężenia zwrotnego, dzięki czemu mogę używać VLC do odtwarzania strumienia przy użyciu adresu multiemisji. Pomijając inne problemy z bitrate i kontrolowanym multicastem, próbowałem odczytać jeden plik wideo i multicast na sprzęcie zwrotnym. Ale kiedy próbował grać tak samo na vlc, to nie zadziałało. Jestem w stanie dostrzec coraz pakiet przesyłany w Wireshark ale ip src pochodzi z mojego domyślnego interfejsu sieciowego (czyli interfejs, który jest moim brama domyślna)

Próbowałem już następujące polecenia

sudo ifconfig lo multicast sudo ip route add 239.252.10.10 dev lo

Wszelkie sugestie w tym zakresie byłyby bardzo pomocne.

kod Program testowy wklejony poniżej

  #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

czy masz jakieś rozwiązanie? Też mam ten sam problem. – user2990252

Odpowiedz

0

pragnę wysłać pakiety UDP multicast do sprzężenia zwrotnego adresu

zatrzymują się tam. Nie możesz tego zrobić. To niemożliwe. Możesz wysyłać tylko multicasty do adresów multiemisji. Twój kod nie wykonuje żadnego rozsyłania, wystarczy wysłać do 127.0.0.1.

Jeśli wysyłasz tylko do hosta lokalnego, dlaczego w ogóle używasz multiemisji? Czy masz wiele procesów odsłuchowych?

ip src pochodzi z mojego domyślnego interfejsu sieciowego (czyli interfejs, który jest moim brama domyślna)

bardzo prawdopodobne, ponieważ nie związały swoje gniazdo. Czego oczekiwałeś?

+0

Adres multiemisji można podać z wiersza poleceń, który jest traktowany jako docelowy adres IP. Zasadniczo chcę transmitować wszystko, co otrzymam, do interfejsu pętli zwrotnej w trybie multiemisji, aby jedna aplikacja mogła je odebrać, aby nagrywać w pliku, podczas gdy inna aplikacja odtwarza je i tak dalej. Właśnie dlatego miejsce docelowe multiemisji jest ustawione dla docelowego adresu IP pakietu udp. –

+0

Dla interfejsu src ip, nawet jeśli podłączę gniazdo do 127.0.0.1 nadal nie przyjmuje tego w pakietach wychodzących. –

+2

@EJP Co jeśli chcę, aby wiele procesów było czytanych z jednego strumienia w sub/pubie? Na przykład wideo na żywo. – Aron

13

Możesz użyć multicast na sprzężeniu zwrotnym, ale musisz dodać nową trasę, ponieważ twój system operacyjny domyślnie używa zewnętrznego interfejsu dla multicast. Również multicast może być wyłączony domyślnie w pętli zwrotnej. Na Linuksie możesz to zmienić za pomocą tego polecenia:

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