UDP客户端/服务器:混合IPv4和IPv6



假设您有一个游戏服务器,仅UDP,在同时具有IPv4和IPv6地址的服务器上运行。服务器启动,调用getaddrinfo((在可用地址中循环,假设它获取IPv6地址。因此,它在IPv6上创建了套接字,并等待来自客户端的数据包。

客户端尝试连接,但这次使用的是用户输入的IPv4地址。它创建一个IPv4套接字,并尝试连接到服务器。差异真的重要吗?还是IPv4套接字和IPv6套接字之间的区别仅限于本地计算机?

同样,如果客户端已经创建了一个IPv6套接字以供使用(因为getaddrinfo((表示它是有效的(,然后它调用getaddrinfo((来查找服务器的地址,那么如果它只得到IPv4结果呢?我知道我可以告诉getaddrinfo((只给出IPv6结果,但如果服务器没有IPv6地址怎么办?UDP客户端是否应该关闭并重新创建其套接字以匹配服务器地址格式?还是我保证能得到我要求的地址格式?

(我欢迎任何回答这些问题的文档参考。我已经研究了几个小时,但还没有找到这些问题的明确答案。(

默认情况下,IPv6 UDP套接字将只发送和接收IPv6 UDP数据包,因此您的IPv4客户端将倒霉。

但是,如果您在双堆栈计算机上运行(您可能是(,则可以在套接字上启用IPv4映射的IPv6地址,然后可以使用该套接字来处理IPv4和IPv6 UDP流量。IPv4数据包将显示为来自一个特殊格式的IPv6地址(格式如"::ffff:1192.168.0.5"(,但除此之外,它们的处理方式与任何IPv6 UDP客户端相同。

您可以在套接字上启用IPv4映射的IPv6地址,如下所示:

int v6OnlyEnabled = 0;  // we want v6-only mode disabled, which is to say we want v6-to-v4 compatibility
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v6OnlyEnabled, sizeof(v6OnlyEnabled)) != 0) perror("setsockopt");

另一种方法是根据需要(在客户端和/或服务器上(创建单独的IPv4和IPv6套接字,但只要有可用的双堆栈网络堆栈,IPv4映射的IPv6地址方法就更容易使用。

最新更新