如何支持IPv4和IPv6连接

时间:2009-10-24 15:15:30

标签: c++ winsock ipv6 sockets ipv4

我目前正在开发UDP套接字应用程序,我需要内置支持,以便IPV4和IPV6连接可以将数据包发送到服务器。

我希望有人可以帮助我,并指出我正确的方向;我发现的大部分文档都不完整。如果你能指出Winsock和BSD套接字之间的任何差异,也会有所帮助。

提前致谢!

4 个答案:

答案 0 :(得分:78)

最好的方法是创建一个也可以接受IPv4连接的IPv6服务器套接字。为此,请创建常规IPv6套接字,将关闭套接字选项IPV6_V6ONLY,将其绑定到“任意”地址,然后开始接收。 IPv4地址将以IPv4-mapped格式显示为IPv6地址。

系统间的主要区别在于IPV6_V6ONLY是否可用,以及b)默认情况下是打开还是关闭。它在Linux上默认关闭(即允许没有setsockopt的双栈套接字),并在大多数其他系统上打开。

此外,Windows XP上的IPv6堆栈不支持该选项。在这些情况下,您需要创建两个单独的服务器套接字,并将它们放入select或多个线程中。

答案 1 :(得分:7)

套接字API由IETF RFC管理,在所有平台上都应该相同,包括Windows WRT IPv6。

对于IPv4 / IPv6应用程序,它是关于getaddrinfo()getnameinfo() ALL getaddrinfo是一个天才 - 查看客户端的DNS,端口名称和功能,以解决“我可以使用IPv4,IPv6或两者到达特定目的地吗?”的永恒问题。或者,如果您要使用双-stack路由并希望它返回IPv4映射的IPv6地址,它也会这样做。

它提供了一个直接的sockaddr *结构,可插入bind()recvfrom()sendto()以及socket()的地址系列...在许多情况下,意味着没有混乱的sockaddr_in(6)结构来填写和处理。

对于UDP实现,我会小心设置双栈套接字,或者更一般地说,绑定到所有接口(INADDR_ANY)。经典的问题是,当地址未被锁定(参见bind())到特定接口并且系统有多个接口请求时,响应可能会根据操作系统路由的异想天开从具有多个地址的计算机的不同地址传输表,混淆应用程序协议 - 尤其是任何具有身份验证要求的系统。

对于没有问题的UDP实施或TCP,双堆栈套接字可以在使用IPv *启用系统时节省大量时间。必须小心不要完全依赖双栈,因为它不是绝对必要的,因为没有合理的平台(旧的Linux,BSD,Windows 2003)部署IPv6堆栈不能兼容双堆栈。

答案 2 :(得分:4)

我一直在Windows下玩这个,它实际上似乎是一个安全问题,如果你绑定到环回地址然后IPv6套接字正确绑定到[:: 1]但映射的IPv4套接字是绑定到INADDR_ANY,因此您(据称)安全的本地应用程序实际上是暴露给世界的。

答案 3 :(得分:3)

RFC并没有真正指定IPV6_V6ONLY套接字选项的存在,但是,如果它不存在,则RFC非常清楚,实现应该就像该选项是FALSE一样。

如果选项存在,我认为它应该默认为FALSE,但是,由于理解的原因,BSD和Windows实现默认为TRUE。有一个奇怪的说法,这是一个安全问题,因为一个不知情的IPv6程序员可以认为他们只绑定到IN6ADDR_ANY只有IPv6,并意外接受IPv4连接导致安全问题。我认为这对于任何期望符合RFC的实现的人来说都是一个既有牵强也有荒谬的事情。

对于Windows,不合规通常不会令人感到意外。就BSD而言,这是不幸的。