【发布时间】:2012-07-27 22:11:45
【问题描述】:
我有一个 UDP 服务器,它必须为 IPV4 和 IPV6 地址上的客户端提供服务。我创建了一个 IPV6 套接字来同时为 IPV4 和 IPV6 客户端提供服务。
服务器在第一次通信时存储客户端的 IPAddress。如果是 IPV4 客户端,则存储为 IPV4 地址,如果是 IPV6 客户端,则服务器存储为 IPV6 地址。对于所有未来的通信,它会检查存储是否该客户端是已知的(存储的),然后采取相应的行动。为了将客户端地址与存储的地址进行比较,我根据系列类型(AF_INET 和 AF_INET6)执行 memcmp。
与 IPV6 客户端通信时,系统工作正常,但与 IPV4 客户端通信时,系统的行为如下如果它从来不认识客户。在调试时,我发现由于 IPV6 的套接字类型,IPV4 客户端的 IPAddresss 被接收为 IPV6 映射的 IPV4 地址,其系列设置为 IPV6。为了解决这个问题,我需要比较 IPV4 存储地址和 IPV6 映射地址。为此,我使用 IPV4 结构的 sin_addr.s_addr 和 IPV6 结构的 sin6_addr.in6_u.u6_addr32。请在下面找到代码 sn-p。
ipv6_clientdata = (const struct sockaddr_in6 *)&sockStor;
ipv4_storeddata = (const struct sockaddr_in *)&(_stData[index].clientaddr);
if( (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) &&
(ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr)
)
{
addrfound = true;
}
我想知道这种方法是否是比较 IPV6 映射的 IPV4 地址与 IPV4 地址的正确解决方案,还是有其他更好的方法。
【问题讨论】:
-
我承认我对 IPv6 还没有太多经验,但不会,例如
recvfrom将源地址返回为AF_INET6,即使它是 IPv6 映射的 IPv4 地址? -
对不起,我跳过/忘了提及以下功能。服务器通过两种方式获取客户端地址。 1) 首次通过 UDP 与客户端通信 2) 客户端可能通过 TCP 将其 UDP 连接详细信息作为 XML 数据发布到服务器。在这种情况下,客户端将只提供 IPV4 地址。
-
在比较最后 32 位之前,您还需要检查前 80 位是否为零,接下来的 16 位是否为 1。否则你不知道你是否正在处理映射为 IPV6 的 IPV4。