sockaddr_in和sockaddr_in6仍在使用sin_len和sin6_len吗?

时间:2016-08-12 08:27:15

标签: linux windows macos sockets

所以,基本上标题就是这么说的。我一直在将我的unix socket C代码移植到Windows,显然这些结构在windows中没有sin_len或sin6_len。

我在sockaddr_storage,sockaddr_in和sockaddr_in6之间使用了一个联合,只是根据ss_family使用了正确的成员。有意义的是,套接字库可以根据族来推断出大小,因此长度字段确实是多余的。

如果我注释掉设置长度字段的代码,那么一切仍然适用于OSX和Linux,但这可能只是一种错觉,所以我决定在这里问一下。 这个变量是不是被弃用了?我可以安全地停止使用它,并依赖套接字实现来使用系列变量吗?

1 个答案:

答案 0 :(得分:3)

POSIX规范不要求sin_len字段。

以下是来自 Unix网络编程 - 第1卷的相关信息.Sockets Networking API,第3版

3.2套接字地址结构

  

长度成员 sin_len ,添加了4.3BSD-Reno,当支持   添加了OSI协议(图1.15)。在此版本之前,   第一个成员是 sin_family ,这在历史上是无符号的   短。并非所有供应商都支持套接字地址的长度字段   结构和POSIX规范不需要此成员。

进一步史蒂文提供了该领域的动力:

  

有一个长度字段简化了可变长度套接字地址结构的处理。

     

即使存在长度字段,我们也不需要设置它,也不需要检查它,除非我们处理路由套接字(第18章)。它在内核中由处理来自各种协议族的套接字地址结构的例程(例如,路由表代码)使用。

     

将进程中的套接字地址结构传递给内核的四个套接字函数 bind,connect,sendto和sendmsg ,都通过 sockargs 函数Berkeley派生的实现(TCPv2的第452页)。此函数从进程复制套接字地址结构,并将其 sin_len 成员显式设置为作为这四个函数的参数传递的结构的大小。从内核向进程传递套接字地址结构的五个套接字函数, accept,recvfrom,recvmsg,getpeername和getsockname ,都会在返回之前设置 sin_len 成员这个过程。

     

不幸的是,通常没有简单的编译时测试来确定实现是否为其套接字地址结构定义了一个长度字段......我们将在图3.4中看到,IPv6实现需要定义 SIN6_LEN 如果套接字地址结构有长度字段。一些IPv4实现基于编译时选项(例如, _SOCKADDR_LEN )向应用程序提供套接字地址结构的长度字段。

您需要在代码中评估sin_len的用法。如果只是将其初始化为0,则可以删除代码。如果您正在从 accept,recvfrom,recvmsg,getpeername或getsockname 的结果中读取值,那么您将不幸需要一些特定于平台的编译开关或切换到使用单独的地址长度变量