将套接字绑定到IPv6地址

我正在尝试编写一个侦听IPv4和IPv6地址的Web服务器。 但是,我最初写的代码不起作用。 然后我发现IPv6结构适用于IPv4和IPv6。 所以现在我使用IPv6结构,但只有IPv4地址才有效。 这篇post, 为什么我不能将ipv6 socket绑定到linklocal地址 ,后面说要添加server.sin6_scope_id = 5; 所以我这样做但它仍然不接受IPv6 telnet连接。 任何帮助将不胜感激,因为我彻底难过。
谢谢!

我的代码如下:

 void initialize_server(int port, int connections, char* address) { struct sockaddr_in6 socket_struct; /*Creates the socket*/ if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }/*Ends the socket creation*/ /*Populates the socket address structure*/ socket_struct.sin6_family = AF_INET6; if(address == NULL) socket_struct.sin6_addr=in6addr_any; else { inet_pton(AF_INET6, "fe80::216:3eff:fec3:3c22", (void *)&socket_struct.sin6_addr.s6_addr); } socket_struct.sin6_port =htons(port); socket_struct.sin6_scope_id = 0; if (bind(sock_fd, (struct sockaddr*) &socket_struct, sizeof(socket_struct)) < 0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }//Ends the binding. if (listen(sock_fd, connections) <0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }//Ends the listening function }//ends the initialize server function. 

您正在AF_INET系列中创建套接字,但之后尝试将其绑定到AF_INET6系列中的地址。 在调用socket()切换到使用AF_INET6

说“server.sin6_scope_id = 5;” 是任意的。 我自己与此争吵了一段时间,发现你需要使用你想要绑定的实际接口的实际范围。 可以发现它具有隐蔽但有用的小function。

 #include  server.sin6_scope_id=if_nametoindex("eth0"); 

当然,将其硬编码到一个特定的适配器是不好的短视编码。 更完整的解决方案是循环遍历所有这些并匹配您绑定的IP地址。 以下并不完美,因为它没有考虑像非规范地址和两个具有相同IP等的适配器等怪癖。但总体而言,这个示例函数效果很好,应该让你开始。

 #include  // strcmp #include  // if_nametoindex() #include  // getifaddrs() #include  // NI_ constants // returns 0 on error unsigned getScopeForIp(const char *ip){ struct ifaddrs *addrs; char ipAddress[NI_MAXHOST]; unsigned scope=0; // walk over the list of all interface addresses getifaddrs(&addrs); for(ifaddrs *addr=addrs;addr;addr=addr->ifa_next){ if (addr->ifa_addr && addr->ifa_addr->sa_family==AF_INET6){ // only interested in ipv6 ones getnameinfo(addr->ifa_addr,sizeof(struct sockaddr_in6),ipAddress,sizeof(ipAddress),NULL,0,NI_NUMERICHOST); // result actually contains the interface name, so strip it for(int i=0;ipAddress[i];i++){ if(ipAddress[i]=='%'){ ipAddress[i]='\0'; break; } } // if the ip matches, convert the interface name to a scope index if(strcmp(ipAddress,ip)==0){ scope=if_nametoindex(addr->ifa_name); break; } } } freeifaddrs(addrs); return scope; }