Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
383 views
in Technique[技术] by (71.8m points)

c - Multicasting on the loopback device

I wish to send UDP multicast packets to loopback address and receive the same in other application. All tests done on fedora core 17 Linux.

The idea is to receive a video stream via RTSP/HTTP or any other network protocol and multicast it on the loopback address so that I can use VLC to play the stream using multicast address. Leaving aside other bitrate and controlled multicast issues, I tried to read one video file and multicast on loopback device. But when tried to play the same on vlc it didn't worked. I'm able to see packet getting transmitted in wireshark but the src ip is taken from my default network interface (i.e interface which is my default gateway)

I have already tried following commands

sudo ifconfig lo multicast
sudo ip route add 239.252.10.10 dev lo

Any suggestion in this regard would be very helpful.

Test program code pasted below

    #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.
");

      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
");
    #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.
");
    #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 
",filepath);
        return -1;
        }
        sd = socket_init(srcip);
        if(sd < 0) {
        printf("Socket initialization failed 
");
        fclose(fp);
        return -1;
        }
        databuf = (char*) malloc(sizeof(char)*DATA_BUFFER_SIZE);
        if(!databuf) {
        printf("Unable to allocate databuf
");
        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
");
            break;
        }           
        if(transmit_packet(sd,databuf,rc,dstip,port) <0)
            printf("Transmit failed
");    
        }
        close(sd);fclose(fp);
        free(databuf);
        return 0;
    }

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

       if(argc != 3){
        printf("%s <filename> <ip>
",argv[0]);
        return -1;
       }
       transmit_file(argv[1],argv[2],INTERFACE_IP,UDP_PORT);
       return 0;
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can use multicast on loopback but you have to add a new route because your OS using default external interface by default for multicast. Also multicast can be disabled by default on loopback. On linux you can change this with this command :

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...