无法设置套接字选项 IPV6 多播:没有这样的设备错误

Unable to set socket options IPV6 multicast : No such device error

我正在研究 linux Ubuntu 14.04 并尝试使用 IPv6 进行多播。我有一个 link 本地地址 fe80::9a90:96ff:fe98:a985。 运行 以下代码:

int main (int argc, char *argv[]) {
  int sd;
  struct in6_addr localInterface;
  /* 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");
  }

  /* Set local interface for outbound multicast datagrams. */
  /* The IP address specified must be associated with a local, */
  /* multicast capable interface. */
  inet_pton (AF_INET6, "fe80::9a90:96ff:fe98:a985", &(localInterface.s6_addr));

  if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&localInterface, sizeof(localInterface)) < 0)
    {
      perror("Setting local interface error");
      printf ("%d\n", errno);
      exit(1);
    }
  else {
    printf("Setting the local interface...OK\n");
  }

}

给出错误:Setting local interface error : No such device

我已经测试了多播与 IPv4 一起工作,并且还成功地测试了 IPv6 通过使用 ping6 命令 ping 本地节点来工作。

通过一些调整,我能够修改你的程序,让它在我的 Mac (运行 OS/X 10.10. 5).我没有在其他 OS 下尝试过它,但它应该或多或少地在其他 OS 上工作。

请注意,该程序已将接口编号硬编码为 4,因为这就是我计算机上的 en0;接口号在您的计算机上可能会有所不同,对于一个通常有用的程序,您希望动态地发现正确的接口号(使用 getifaddrs() or GetAdaptersAddresses() 或类似的);为简单起见,此处仅进行了硬编码。

修改后的程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

int main (int argc, char *argv[]) 
{
   int 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");

   // 4 is the interface ID (scope_id) of interface en0 on my Mac,
   // as printed by ifconfig; the appropriate interface index 
   // value on your computer will likely be different  --jaf
   int my_network_devices_scope_id = 4;

   if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&my_network_devices_scope_id, sizeof(my_network_devices_scope_id)) < 0)
   {
       perror("Setting local interface error");
       printf ("%d\n", errno);
       exit(1);
   }
   else printf("Setting the local interface...OK\n");

   struct sockaddr_in6 multicastIP;
   multicastIP.sin6_family   = AF_INET6;
   multicastIP.sin6_scope_id = my_network_devices_scope_id;
   multicastIP.sin6_port     = htons(9999);  // destination port chosen at random
   inet_pton(AF_INET6, "ff12::bead:cede:deed:feed", &multicastIP.sin6_addr.s6_addr);  // a multicast address I chose at random

   while(1)
   {
       char buf[] = "hello";
       if (sendto(sd, buf, sizeof(buf), 0, (const struct sockaddr *) &multicastIP, sizeof(multicastIP)) == sizeof(buf))
       {
          printf("Sent a %i-byte multicast packet!\n", (int) sizeof(buf));
       }
       else perror("sendto");

       sleep(1);
   }

   return 0;
}