无法使用IPv6进行多播

时间:2015-09-16 01:29:47

标签: c ipv6

以下是发件人和收件人的代码(合并)。

int main (int argc, char *argv[]) {
  struct in6_addr localInterface;
  struct sockaddr_in6 groupSock;
  // socket descriptor for multicast
  int sd;

  char databuf[10];
  // length of message
  int datalen = sizeof(databuf);

  /* Create a datagram socket on which to send/receive. */
  sd = socket(AF_INET6, SOCK_DGRAM, 0);

  if(sd < 0) {
    perror("Opening datagram socket error");
    exit(1);
  }
  else {
    printf("Opening the datagram socket...OK.\n");
  }

  /* Enable SO_REUSEADDR to allow multiple instances of this */
  /* application to receive copies of the multicast datagrams. */
  {
    int reuse = 1;
    if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
      {
    perror("Setting SO_REUSEADDR error");
    close(sd);
    exit(1);
      }

    else {
      printf("Setting SO_REUSEADDR...OK.\n");
    }
  }

  /* Initialize the group sockaddr structure with a */
  memset((char *) &groupSock, 0, sizeof(groupSock));
  groupSock.sin6_family = AF_INET6;
  // address of the group
  // groupSock.sin6_addr = inet6_addr("ff5e::/16");
  inet_pton(AF_INET6, "ff5e::/16", &(groupSock.sin6_addr));

  groupSock.sin6_port = htons(4321);

  /* Set local interface for outbound multicast datagrams. */
  /* The IP address specified must be associated with a local, */
  /* multicast capable interface. */
  char *ip_address = argv[2];
  inet_pton (AF_INET6, ip_address, &(localInterface.s6_addr));

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

  int ifindex;
  ifindex = if_nametoindex ("eth5");
  printf ("ifindex is %d\n", ifindex);

  if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)))
    {
      perror("Setting local interface error");
      exit(1);
    }
  else {
    printf("Setting the local interface...OK\n");
  }

  // choice is 0 for sending and 1 for receiving
  int choice;
  sscanf (argv[1], "%d", &choice);

  // if sending
  if (choice == 0) {
    int i;
    for (i = 0; i < datalen-1; ++i) {
      databuf[i] = 'a';
    }
    databuf[i] = 0;

    if (sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0) {
      printf ("Error in send\n");
    }

    else {
      printf ("Send okay!\n");
    }
  }

  // if receiving
  else if (choice == 1) {
    groupSock.sin6_addr = in6addr_any;
    if(bind(sd, (struct sockaddr*)&groupSock, sizeof(groupSock))) {
      perror("Binding datagram socket error");
      close(sd);
      exit(1);
    }

    else {
      printf("Binding datagram socket...OK.\n");
    }

    /* Join the multicast group ff5e::/16 on the local  */
    /* interface. Note that this IP_ADD_MEMBERSHIP option must be */
    /* called for each local interface over which the multicast */
    /* datagrams are to be received. */
    struct ipv6_mreq group;
    inet_pton (AF_INET6, "ff5e::", &(group.ipv6mr_multiaddr.s6_addr));

    // group.imr_interface.s6_addr = inet_addr(ip_address);
    group.ipv6mr_interface = ifindex;

    if(setsockopt(sd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
      perror("Adding multicast group error");
      close(sd);
      exit(1);
    }

    else {
      printf("Adding multicast group...OK.\n");
    }

    if (read(sd, databuf, datalen) < 0) {
      perror("Error in read");
    }

    else {
      printf("Read Okay\n");
      printf ("Message is : %s\n", databuf);
    }
  }

}

如果发送方和接收方位于不同的节点上,接收方不会收到消息(我已经检查过它们是否通过ping6连接)。我正在使用Linux Ubuntu 14.04。使用tcpdump捕获ipv6数据包会发现数据包不是在发送方发送的。有什么问题?

1 个答案:

答案 0 :(得分:2)

一个问题是您的IPv6多播地址选择不当。 FF5E::像这样分解:

  • FF表示它是多播。
  • 5是标志集(0101),此值是一组无效的标志。最高位设置意味着您有一个嵌入式RP地址,您显然不会这样做。为此,标志集必须为70111),然后遵循嵌入RP地址的所有规则。
  • E表示它是全局范围。

应该在与路由器相遇的任何路径中正确删除此多播地址。

请参阅RFC 4291,3306和3956以创建IPv6多播地址,包括标志和范围的含义。