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

时间:2010-03-01 15:38:36

标签: linux sockets

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

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

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

5 个答案:

答案 0 :(得分:6)

使用1个TCP套接字无法监听2个不同的IP地址,但是如果使用in6addr_any地址监听所有接口,那么也会包含所有IPv4地址(尽管我相信例如linux已经一个内核选项来禁用该映射。)

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

e.g。此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));

必须转换为以下处理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));

虽然我相信你可以用getaddrinfo()

更优雅和透明地做到这一点

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

答案 1 :(得分:4)

IPv4和IPv6的大部分套接字处理都是相同的。在服务器上,一旦绑定了地址,对listenacceptrecvsend的调用对于IPv4和IPv6连接都将起作用。< / p>

但是,任何处理connectbindgetsocknamegetpeername等地址的函数都需要修改,因为您需要使用{{1} }。此外,您需要修改使用地址的函数(例如,对sockaddr_in6的调用需要更改为inet_addr)。

在Linux上,如果绑定到inet_pton,那么到该端口的IPv4和IPv6连接都将起作用(尽管这可以侦听超过2个地址,因为它也会侦听IPv4环回{{1}和IPv6环回in6addr_any)。但是在Windows上,我从来没有能够让它工作,需要在一个插槽上侦听IPv4和一个不同的IPv6套接字。

答案 2 :(得分:2)

Beej的网络编程指南解决了IPv4和IPv6编码的差异。 http://beej.us/guide/bgnet/

他专注于改变现有IPv4代码以处理IPv6。

他还解释了如何在套接字级别抽象编码,这样您就不需要知道是在处理IPv4地址还是IPv6。

答案 3 :(得分:0)

我认为存在差异,主要是如何分配/显示IP地址以及子网掩码。

获取传入IPv4地址的方法将无效并且如果为其提供纯IPv6则抛出异常,因此您的方法将需要检查启动了哪种连接,除此之外我不这么认为

答案 4 :(得分:0)

IPv6是128位地址空间,与IPv4(32位)相比,提供了更多功能(无状态,多播,路由器简单处理,仅举几例),地址空间为IPv4即将耗尽,但在NAT / SNAT的帮助下,它可能会延长IPv4协议的使用寿命。使用IPv6取决于操作系统是否可以支持新协议。它当然可以在Windows 7,Linux上使用......主要的是IPv6向后兼容IPv4 ...

要回答您的问题,这取决于操作系统可以支持IPv6网络堆栈的API级别。以下是MSDNLinux上的IPv6套接字示例的示例,用于{{3}},套接字大致相同,但您将使用sockaddr_in6 ...

希望这有帮助, 最好的祝福, 汤姆。