gpt4 book ai didi

c - 套接字系列函数如何处理不同类型的结构?

转载 作者:太空宇宙 更新时间:2023-11-04 08:28:12 24 4
gpt4 key购买 nike

socket 函数、connect、bind、accept 等如何处理具有不同大小的不同类型的结构?例如,connect() 将 struct sockaddr 作为其第二个参数,但也可以传递 struct sockaddr_in 或 struct sockaddr_in6,前提是第三个参数 socklen_t namelen 具有正确的值。但实际上,这些结构具有不同的格式:

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

struct sockaddr_in {
uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

struct sockaddr_in6 {
uint8_t sin6_len;
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};

struct sockaddr_storage {
uint8_t ss_len;
sa_family_t ss_family;
/* implementation-dependent fields */
};

这些结构似乎没有任何共同点(实际上,只有 sin_len 和 ss_family,但 sin_len 本身不可移植,并非所有平台都支持它),但我们对它们都使用相同的函数。我不认为这些函数仅仅依赖于第三个参数(namelen),因为依赖于一个对象的实际大小,来确定它的类型,是不可移植的。

最佳答案

这些结构的一个共同点是它们都以一个 family 字段开始(len 字段并非在所有平台上都存在)所有 sockaddr_... 类型的偏移量和大小。该字段加上套接字的实际地址类型(由 socket()accept() 建立)足以让每个函数验证任何 的大小和格式>sockaddr 你传入,因此他们可以报告不匹配的错误。

sockaddr_storage 设计得足够大以容纳任何其他 sockaddr_... 结构类型。您可以将 sockaddr_storage 传递给任何函数。您可以将其类型转换为任何其他 sockaddr_... 类型。因此,您可以根据 ss_family 字段对 sockaddr_storage 进行类型转换。对于输入,类型转换为所需的 sockaddr_... 类型并根据需要填充其字段,包括 family。对于输出,查看 ss_family 字段,然后根据需要将类型转换为适当的 sockaddr_... 类型。

例如,如果套接字的地址类型是AF_INET (IPv4),connect() 要求sockaddr 缓冲区位于sockaddr_in 格式和 namelen 参数至少为 sizeof(sockaddr_in)。同样,accept()sockaddr_in 格式的数据填充 sockaddr 缓冲区,并且 addrlen 参数必须至少为sizeof(sockaddr_in)

对于 AF_INET6 (IPv6),将 sockaddr_in 替换为 sockaddr_in6

这同样适用于其他功能。

通常,sockaddr 缓冲区的大小必须足够大以容纳属于套接字地址类型的正确的sockaddr_... 结构。接受地址作为输入的函数(connect()bind()sendto())需要将缓冲区格式化为正确的格式sockaddr_... 格式。返回地址作为输出的函数(accept()recvfrom())将使用适当的sockaddr_... 类型格式化数据。

关于c - 套接字系列函数如何处理不同类型的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29463816/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com