套接字级别的IPv4和IPv6之间有什么区别吗?

Hai*_*ang 9 sockets linux

我需要为现有的基于套接字的应用程序添加IPv6支持,该应用程序目前仅支持IPv4.为了迎接即将到来的IPv6时代,有人命令我为应用程序添加IPv6接口,让外界在尝试与应用程序通信时选择IPv4接口或IPv6接口.

我的问题是:对于Linux中的套接字处理API级别,处理基于IPv4的套接字和基于IPv6的套接字之间没有区别吗?

更进一步,是否可以让套接字侦听具有相同端口的两个IP地址?如果这是真的,那么实现这个要求是一项微不足道的工作,我想.

nos*_*nos 6

用1个TCP套接字监听2个不同的IP地址是不可能的,但是如果你使用in6addr_any地址监听所有接口,那么也将包括所有的IPv4地址(虽然我相信例如linux有一个内核选项来禁用该映射).

(较新版本)套接字API对于您使用的是IPv4还是IPv6非常透明,但必须非常谨慎地考虑IPv4应用程序的编码方式.

例如,这个IPv4代码接受连接并打印出远程主机的地址:

 struct sockaddr_in client_addr;
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 log_printf("New client from %s\n",inet_ntoa(client_addr.sin_addr.s_addr));
Run Code Online (Sandbox Code Playgroud)

必须转换为以下内容,它处理IPv4和IPv6

 struct sockaddr_storage client_addr;
 char numeric_addr[INET6_ADDRSTRLEN];
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 if(client_addr.ss_family == AF_INET)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in*)&client_addr)->sin_addr.s_addr ,numeric_addr,sizeof numeric_addr));
 else if(client_addr.ss_family == AF_INET6)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in6*)&client_addr)->sin6_addr ,numeric_addr,sizeof numeric_addr));
Run Code Online (Sandbox Code Playgroud)

虽然我相信你可以用getaddrinfo()更优雅和透明地做到这一点

以下是关于IP层独立性的附加说明:http : //uw714doc.sco.com/en/SDK_netapi/sockC.PortIPv4appIPv6.html http://www.kame.net/newsletter/19980604/


R S*_*hko 5

IPv4 和 IPv6 的大部分套接字处理是相同的。在服务器上,一旦你绑定你的地址,到电话listenacceptrecv并且send将所有的工作同为IPv4和IPv6连接。

但是,任何函数处理,如地址connectbindgetsocknamegetpeername将需要修改的,因为你需要使用sockaddr_in6。此外,您还需要修改处理地址的函数(例如,调用inet_addr需要更改为inet_pton)。

在 Linux 上,如果您绑定到in6addr_any,则到该端口的 IPv4 和 IPv6 连接都将起作用(尽管这将侦听超过 2 个地址,因为它还将侦听 IPv4 环回127.0.0.1和 IPv6 环回::1)。但是在 Windows 上,我一直无法让它工作,需要在一个套接字上侦听 IPv4 和一个不同的套接字上侦听 IPv6。

  • 在 Windows 中,Vista 通过重新设计的双栈套接字堆栈体系结构引入了单个套接字在单个端口上侦听和接受 IPv4 和 IPv6 客户端的能力。创建一个 IPv6 侦听套接字并将新的 IPV6_V6ONLY 套接字选项设置为 False 以允许 IPv4 客户端在其上。 (3认同)