【问题标题】:How to get actual size of ai_addr->sa_data returned by getaddrinfo()如何获取 getaddrinfo() 返回的 ai_addr->sa_data 的实际大小
【发布时间】:2014-09-21 12:30:55
【问题描述】:
getaddrinfo() 填充struct addrinfo,其中实际打包地址存储在struct sockaddr *ai_addr 字段中。 struct sockaddr 的字段 char *sa_data 具有实际的二进制地址表示。我想使用memcpy() 将此 sa_data 复制到另一个变量,为此我需要知道该字段的实际长度。
我认为 ai_addrlen 是我需要的。但实际上它为 IPv4 返回 16,为 IPv6 返回 28。我想太多了。那么,获取 sa_data 长度的最正确方法是什么?可能是length = sa_family == AF_INET ? 4 : 16 或length = ai_addrlen - 12?
【问题讨论】:
标签:
c
network-programming
getaddrinfo
【解决方案1】:
getaddrinfo() 函数返回一个由struct addrinfo 记录组成的链表。这些记录中的每一个都包含一个指向struct sockaddr 的指针,它是一种多态类型,在其后面实际上有一个struct sockaddr_in 或struct sockaddr_in6。 ai_addrlen 成员告诉您该结构有多大,即返回 sizeof (struct sockaddr_in) 或 sizeof (struct sockaddr_in6)。
这些结构包含二进制 IP 地址、端口号(用于 TCP 或 UDP 等传输协议)、系列(在struct addrinfo 中也重复)和其他数据(在查看 linux 时,用于 IPv6 的 flowinfo 和 scope_id文档)。
实际的二进制地址在struct sockaddr_in 和strict sockaddr_in6 内,如struct in_addr sin_addr 和struct in6_addr sin6_addr。您可以使用这些字段或类型来确定大小。
length = sa_family == AF_INET ? sizeof (struct in_addr) : sizeof (struct in6_addr)
由于这些是已知数字,您当然可以使用问题中已有的内容。
length = sa_family == AF_INET ? 4 : 16
但是您还尝试对 ai_addrlen 进行算术运算,这不是一个好主意,因为类型可能因操作系统而异,而且无论如何都没有逻辑。如果您有特定用例或特定代码,我可以添加更多详细信息。