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个字符将足够宽,以适应未来的所有类型。
发布于 2015-09-17 16:01:42
根据glibc manual的说法
sa_data的长度14本质上是任意的。
FreeBSD developers handbook提到了以下几点:
请注意sa_data字段声明的模糊性,就像14个字节的数组一样,注释提示可能超过14个字节。
套接字是一个非常强大的接口。虽然大多数人可能认为套接字只不过是Internet接口-现在大多数应用程序可能都在使用它-但套接字几乎可以用于任何类型的进程间通信,而Internet (或者更准确地说,IP)只是其中之一。
是的,sa_family
字段用于识别如何处理传递的结构(该结构在绑定调用中强制转换为struct sockaddr*
)。你也可以在FreeBSD developers handbook中阅读更多关于它是如何工作的内容。
实际上,存在“多态”(Sub)类型的sockaddr
,其中sa_data
包含超过16个字节,例如:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
发布于 2015-09-17 16:15:47
sockaddr
结构用作带标记的联合。通过读取sa_family
字段,可以将其转换为适当形式的结构。
这14个字节是任意的。它的大小足以容纳IPv4地址,但不足以容纳IPv6地址。还有一个sockaddr_storage
结构,它足够大,可以同时满足这两种情况。在SOCKADDR_STORAGE上阅读微软文档时,它有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字节。
https://stackoverflow.com/questions/32624847
复制相似问题