如何在相同端口上同时创建支持IPv4与IPv6的Socket?
同一端口同时支持IPv4和IPv6 Socket的实现方案
报错原因
默认情况下,大多数Linux/UNIX系统的IPv6套接字未开启IPV6_V6ONLY选项时,会同时监听IPv4和IPv6的连接请求,相当于同时占用了该端口的IPv4、IPv6双栈。你先绑定了IPv4的8888端口,再绑定IPv6的8888端口时,系统会判定端口已被占用,因此抛出Address already in use错误。
两种实现方案
方案1:仅使用单个IPv6套接字(推荐)
不需要分别创建IPv4和IPv6两个套接字,默认配置下的IPv6套接字可以自动兼容IPv4请求,IPv4地址会被映射为::ffff:<IPv4地址>的格式,无需额外处理即可同时响应两种协议的请求,代码更简洁:
#include<stdio.h> #include<string.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> int main(int argc , char *argv[]) { int socket_desc6; struct sockaddr_in6 server6; // 只创建IPv6套接字 socket_desc6 = socket(AF_INET6 , SOCK_STREAM , 0); if (socket_desc6 == -1) { printf("Could not create socket"); return 1; } puts("IPv6 Socket created"); server6.sin6_family = AF_INET6; server6.sin6_addr = in6addr_any; server6.sin6_port = htons(8888); if( bind(socket_desc6,(struct sockaddr *)&server6 , sizeof(server6)) < 0) { perror("bind failed. Error"); return 1; } puts("bind done, support both IPv4 and IPv6"); listen(socket_desc6 , 3); sleep(30); return 0; }
方案2:分开创建两个套接字
如果你确实需要分别处理IPv4和IPv6的连接,可以在绑定IPv6套接字前,通过setsockopt开启IPV6_V6ONLY选项,强制该套接字仅处理IPv6请求,就不会和IPv4套接字的端口冲突。
在你原有代码的「创建IPv6套接字后、绑定操作前」添加如下代码即可:
int opt = 1; if (setsockopt(socket_desc6, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) < 0) { perror("setsockopt IPV6_V6ONLY failed"); return 1; }
内容的提问来源于stack exchange,提问作者Anis_Stack
相关产品推荐
相关产品推荐

