【问题标题】:Best Way to implement Socket Interface to support both IPV6 and IPV4实现 Socket 接口以支持 IPV6 和 IPV4 的最佳方式
【发布时间】:2011-08-18 22:51:10
【问题描述】:

实现支持 IPV6 的套接字接口的最佳方法是什么。 现有代码仅支持 IPV4。现在,要支持 IPV6,我也没有什么疑问...

1) _我应该用 IPV6 API 替换所有 IPV4 的 API。比如说 AF_INET6 的 AF_INET,sockaddr_in6 的 sockaddr_in 等等。这些新的 API 会支持这两种协议吗?

2) 还是我应该保持这种状态...

#ifdef IPV6_SUPPORT
    sockaddr_in6 addr;
    RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
    addr.sin6_family = AF_INET6;
    addr.sin6_port   = (unsigned short)htons( port );
    RTMemoryUtil::memcpy( &addr.sin6_addr, address, (int)sizeof( *address ) );
#else
    sockaddr_in  addr;
    RTMemoryUtil::memset( &addr, 0, (int)sizeof( addr ) );
    addr.sin_family = AF_INET;
    addr.sin_port   = (unsigned short)htons( port );
    RTMemoryUtil::memcpy( &addr.sin_addr, address, (int)sizeof( *address ) );
#endif

请提出是否有更好的方法或第二个过程有什么缺陷。

【问题讨论】:

  • “非此即彼”将不起作用。 “两者”是目前要走的路。

标签: c++ sockets ipv6


【解决方案1】:

要么使用现代网络编程库,例如 Boost.Asio,要么(如果你想使用 C/sockets 方式)getaddrinfo 接口。后者是大约十年前设计的,因此它应该几乎可以在任何地方使用(至少 Windows、Linux、BSD、Mac OS X)。它还具有额外的魅力,即它还可以支持奇异的网络协议,并提供适当的 OS/C 库支持,因此您可以声称支持独立于协议的分布式云计算®。

【讨论】:

    【解决方案2】:

    根据目标平台,如果实施了合适的双栈,您可以设置套接字选项以使套接字能够同时处理 IPv4 和 IPv6。它将代表您删除大部分工作。

    http://long.ccaba.upc.es/long/045Guidelines/eva/ipv6.htmlhttp://msdn.microsoft.com/en-us/library/bb513665(v=vs.85).aspx 可能有助于开始。

    对于许多用途,它可能与您现有的 IPv4 代码没有太大变化。

    【讨论】:

      【解决方案3】:

      从技术上讲,无论是选项 (1) 还是 (2),您都应该迁移到与 IP 系列无关的 API,并使用 struct sockaddrstruct sockaddr_storage 而不是 IPv4 和 IPv6 硬连线结构。 Stevens 给出了创建不可知 API 的很好示例,这是我采用的类似方法:

      http://code.google.com/p/openpgm/source/browse/trunk/openpgm/pgm/sockaddr.c

      【讨论】:

        【解决方案4】:

        其他答案都在目标上,但还有另一件重要的事情需要考虑:sockaddr 结构比 IPv6 所需的 sockaddr_in6 结构更小。我正在移植具有以下内容的代码:

        struct sockaddr salocal;
        struct sockaddr_in * s_in = (struct sockaddr_in *) &salocal;
        

        将第二行替换为:

        struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
        

        会导致问题,因为虽然sockaddr_in 适合sockaddr,但sockaddr_in6 不适合!但是,sockaddr_storage 足够大,可以同时处理 IPv4 和 IPv6。

        改为改为:

        struct sockaddr_storage salocal;
        struct sockaddr_in6 * s_in6 = (struct sockaddr_in6 *) &salocal;
        

        然后,当调用 bind 之类的方法时,强制转换为 (struct sockaddr *)

        【讨论】:

          猜你喜欢
          • 2010-12-09
          • 1970-01-01
          • 2013-02-16
          • 2010-11-20
          • 1970-01-01
          • 2021-09-24
          • 2012-05-09
          • 1970-01-01
          • 2014-03-07
          相关资源
          最近更新 更多