Thread: Issue with multicast when socket isn't bound to INADDR_ANY

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    90

    Issue with multicast when socket isn't bound to INADDR_ANY

    If I create a socket bound to INADDR_ANY, then bind to a multicast address (say 230.4.4.1) on one or more interfaces (say 192.168.1.1 and 192.168.2.1), that socket will receive packets sent to 230.4.4.1 that are received on either 192.168.1.1 or 192.168.2.1 as expected.

    However, if I create a socket bound to a specific address (say 192.168.1.1), then bind to multicast address 230.4.4.1) on 192.168.1.1 and 192.168.2.1, that socket will NOT receive packets sent to 230.4.4.1 that are received on 192.168.1.1.

    This happens on Linux 2.6 and Solaris 10 but not Windows XP. Under XP, multicast works whether I bind the socket to INADDR_ANY or a specific address.

    Anyone come across this before? Any idea how to fix it?

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    90
    Here's some code that demos the problem:

    The receiver:
    Code:
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <netinet/in.h>
    #include <strings.h>
    
    int sock;
    
    int main(int argc, char *argv[])
    {
      int addr_len;
      struct sockaddr_in sin,sin_recv;
      struct ip_mreq multi;
      char mes[255];
    
      bzero(&sin,sizeof(sin));
      multi.imr_multiaddr.s_addr=inet_addr("230.4.4.1");
      multi.imr_interface.s_addr=inet_addr("192.168.1.6");  // Fill in with your local IP
      sin.sin_family = AF_INET;
      // With this line uncommented, it works
      //sin.sin_addr.s_addr=INADDR_ANY;
      // With this line uncommented, it doesn't work
      sin.sin_addr.s_addr=inet_addr("192.168.1.6");  // Fill in with your local IP
      sin.sin_port = htons(1044);
      if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
        perror("Error creating socket");
        exit(1);
      }
      if (bind(sock,(struct sockaddr *)&sin,sizeof(sin))==-1) {
        perror("Error binding socket");
        close(sock);
        exit(1);
      }
      if (setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&multi,sizeof(multi))== -1) {
        perror("Error joining multicast group");
        close(sock);
        exit(1);
      }
      while (1) {
        bzero(mes,sizeof(mes));
        bzero(&sin_recv,sizeof(sin_recv));
        addr_len=sizeof(sin_recv);
        printf("Waiting for packet...\n");
        if (recvfrom(sock,mes,sizeof(mes),0,(struct sockaddr *)&sin_recv,&addr_len)==-1) {
          perror("error recving socket");
          close(sock);
          exit(1);
        }
        printf("Got packet\n");
        printf("Origin: %s port %d\n",inet_ntoa(sin_recv.sin_addr),sin_recv.sin_port);
        printf("Message: %s\n",mes);
      }
      return 0;
    }
    The sender:
    Code:
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <strings.h>
    
    int sock;
    
    int main(int argc, char *argv[], char *envp[])
    {
      struct sockaddr_in sin;
      struct in_addr out_addr;
      char mes[255], ttl;
      int c;
    
      ttl=1;
      out_addr.s_addr=htonl(INADDR_ANY);
      while ((c = getopt(argc, argv, "t:I:")) != EOF)
        switch (c) {
        case 't':
          ttl=optarg[0];
          break;
        case 'I':
          if (inet_addr(optarg)!=-1)
            out_addr.s_addr=inet_addr(optarg);
          break;
        case '?':
          printf("Unknown option: %s\n",optarg);
          break;
        }
      argc-=optind;
      argv+=optind;
      printf("Enter message: ");
      fgets(mes,sizeof(mes),stdin);
      bzero(&sin,sizeof(sin));
      sin.sin_family=AF_INET;
      sin.sin_addr.s_addr=inet_addr(argv[0]);
      sin.sin_port=htons(atoi(argv[1]));
      if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
        perror("Error creating socket");
        exit(1);
      }
      if (setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,(char *)&ttl,sizeof(ttl))== -1) {
        perror("Error setting ttl");
        close(sock);
        exit(1);
      }
      if (setsockopt(sock,IPPROTO_IP,IP_MULTICAST_IF,(char *)&out_addr,sizeof(out_addr))== -1) {
        perror("Error setting outgoing interface");
        close(sock);
        exit(1);
      }
      if (sendto(sock,mes,strlen(mes),0,(struct sockaddr *)&sin,sizeof(sin))==-1) {
        perror("Send error");
      }
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. socket programming issue
    By santarus in forum C Programming
    Replies: 11
    Last Post: 10-20-2011, 12:14 PM
  2. Issue receiving data from socket (multicast)
    By JessH in forum C++ Programming
    Replies: 11
    Last Post: 08-31-2010, 09:01 AM
  3. socket stays bound after program terminates
    By Elkvis in forum Linux Programming
    Replies: 8
    Last Post: 01-25-2010, 12:54 PM
  4. Sockets, multi home, multicast, security, complicated issue
    By ekymk in forum Networking/Device Communication
    Replies: 6
    Last Post: 08-13-2004, 02:12 AM
  5. CPU-bound and I/O bound
    By jacktibet in forum Linux Programming
    Replies: 3
    Last Post: 11-11-2003, 12:16 PM