比较IPV4套接字(sockaddr_in)和IPV6套接字(sockaddr_in6)

Din*_*.R. 5 c++ sockets udp

我有一个UDP服务器,它必须在IPV4和IPV6地址上为客户端提供服务.我创建了一个IPV6套接字来为IPV4和IPV6客户端提供服务.

服务器在第一次通信时存储客户端的IPAddress.如果它是IPV4客户端,则它存储为IPV4地址,如果是IPV6客户端,则服务器存储为IPV6地址.对于将来的所有通信,它会检查存储器是否已知(存储)此客户端,然后相应地执行操作.为了比较客户端地址和存储的地址,我根据族类型(AF_INET和AF_INET6)执行memcmp.

在与IPV6客户端通信时,系统正常工作,但在与IPV4客户端通信时,系统表现得好像从不知道客户端.在调试时我发现由于IPV6的套接字类型,IPV4客户端的IPAddress被接收为IPV6映射的IPV4地址,其中系列设置为IPV6.要解决这个问题,我需要比较IPV4存储地址和IPV6映射地址.为此我使用了IPV4结构的sin_addr.s_addr和IPV6结构的sin6_addr.in6_u.u6_addr32.请在下面找到代码段.

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;
}
Run Code Online (Sandbox Code Playgroud)

我想知道这种方法是否是将IPV6映射IPV4地址与IPV4地址进行比较的正确解决方案,还是有其他更好的方法.

Cel*_*ada 2

正如Joachim Pileborg推理的那样,当 IPv4 地址来自同一套接字上接收的较早数据包时,您无需关心这一点,因为您将比较一个映射的 IPv4 地址与另一个地址。只有在 IPv4 地址是从外部源获取的情况下,您才需要注意。

\n\n

正如Jo\xc3\xa3o Augusto指出的那样,在比较最后 32 位之前,您忽略了检查 IPv6 地址是否确实是 IPv4 映射地址。有一个宏IN6_IS_ADDR_V4MAPPED可以帮助你做到这一点:

\n\n
if (\n    IN6_IS_ADDR_V4MAPPED(&(ipv6_clientdata->sin6_addr)) &&\n    (ipv6_clientdata->sin6_port == ipv4_storeddata->sin_port) &&\n    (ipv6_clientdata->sin6_addr.in6_u.u6_addr32[3] == ipv4_storeddata->sin_addr.s_addr)\n) {\n    addrfound = true;\n}\n
Run Code Online (Sandbox Code Playgroud)\n