sockaddr中sa_data字段的用途是什么?

时间:2015-09-17 07:34:29

标签: c sockets struct network-programming bind

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

为addr参数传递的实际结构将取决于地址族。 sockaddr结构定义为:

struct sockaddr {
    sa_family_t sa_family;
    char        sa_data[14];
}

因此,对于IPv4地址(AF_INET),将传递的实际结构是:

/* Source http://linux.die.net/man/7/ip */

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address. */
struct in_addr {
    uint32_t       s_addr;     /* address in network byte order */
};

绑定代码是否读取sockaddr.sa_family值并根据它找到的值,然后将sockaddr结构转换为适当的结构,例如sockaddr_in

为什么sa_data设置为14个字符?如果我理解正确,sa_data字段只是一个具有足够大的内存空间以适合所有地址族类型的字段?据推测,原始设计师预计14个字符的宽度足以适应所有未来类型。

2 个答案:

答案 0 :(得分:5)

根据glibc manual

  

sa_data的长度14基本上是任意的。

FreeBSD developers handbook提及以下内容:

  

请注意声明sa_data字段的模糊性,   就像一个14字节的数组一样,注释暗示可以   其中超过14个。

     

这种含糊不清是非常刻意的。套接字非常强大   接口。虽然大多数人可能认为它只不过是   互联网接口 - 大多数应用程序可能会使用它   nowadays-socket可以用于几乎任何类型的进程   通信,其中只有互联网(或更确切地说是IP)   之一。

是的,sa_family字段用于识别如何处理传递的结构(在绑定调用中强制转换为struct sockaddr*)。您可以在FreeBSD developers handbook

中详细了解它的工作原理

实际上有"多态" (子)sockaddr的类型,其中sa_data包含超过16个字节,例如:

struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[108];            /* pathname */
};

答案 1 :(得分:3)

sockaddr结构用作标记联合。通过阅读sa_family字段,可以将其转换为正确形式的结构。

14个字节是任意的。它足以容纳IPv4地址,但不足以容纳IPv6地址。还有一个sockaddr_storage结构,对于两者都足够大。阅读SOCKADDR_STORAGE上的Microsoft文档,它以128字节为单位,比IPv6所需的大得多。检查一些Linux标题,它似乎至少也是那么大。

作为参考,IPv6结构是:

struct sockaddr_in6 {
    u_int16_t       sin6_family;   // address family, AF_INET6
    u_int16_t       sin6_port;     // port number, Network Byte Order
    u_int32_t       sin6_flowinfo; // IPv6 flow information
    struct in6_addr sin6_addr;     // IPv6 address
    u_int32_t       sin6_scope_id; // Scope ID
};

struct in6_addr {
    unsigned char   s6_addr[16];   // IPv6 address
};

如您所见,16字节s6_addr字段已经大于它自己的14字节sa_data字段。 sa_family字段后的总大小为26个字节。