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
?
最佳答案
getaddrinfo()
函数返回一个由 struct addrinfo
记录组成的链表。每条记录都包含一个指向 struct sockaddr 的指针,它是一种多态类型,其后面实际上有一个 struct sockaddr_in 或 struct sockaddr_in6 。 ai_addrlen
成员告诉您该结构有多大,即返回 sizeof (struct sockaddr_in)
或 sizeof (struct sockaddr_in6)
。
这些结构包含二进制 IP 地址、端口号(对于 TCP 或 UDP 等传输协议(protocol))、系列(也在 struct addrinfo 中重复)和其他数据(用于 TCP 或 UDP 的 flowinfo 和scope_id) IPv6,查看 Linux 文档时)。
实际的二进制地址位于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
进行算术运算,这不是一个好主意,因为类型可能会因操作系统而异,而且无论如何都没有逻辑。如果您有特定的用例或特定的代码,我可以添加更多详细信息。
关于c - 如何获取 getaddrinfo() 返回的 ai_addr->sa_data 的实际大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25959188/