如何使用 recvfrom 获取 AF_INET6 套接字的地址
Posted
技术标签:
【中文标题】如何使用 recvfrom 获取 AF_INET6 套接字的地址【英文标题】:How to get an addres of AF_INET6 socket with recvfrom 【发布时间】:2013-08-20 21:34:23 【问题描述】:recvfrom
要求第 5 个参数是指向 sockaddr
结构的指针,第 6 个参数是指向 socklen_t
的指针。
man recvfrom (3)
说:
如果地址的实际长度大于 提供的 sockaddr 结构,存储的地址将被截断。
我不明白如何使用 AF_INET6 地址族检索发送套接字的地址,因为sockaddr_in6
的大小大于sockaddr
,因此它将被recvfrom
截断。
recvfrom
无法检索大于sizeof(sockaddr)
的地址,我理解了吗?
即使我定义sockaddr_in6
的实例将其地址转换为sockaddr*
并将其传递给recvfrom
,我是否理解正确,该函数将无法知道有足够的空间来存储地址?
【问题讨论】:
【参考方案1】:将其转换为sockaddr*
是正确的。
此外,人们经常使用sockaddr_storage
,因为它是defined
标题应定义 sockaddr_storage 结构。 该结构应为:
足够大,可以容纳所有受支持的特定于协议的地址结构 在适当的边界对齐,以便指向它的指针可以转换为指向协议特定地址结构的指针并用于 在没有对齐问题的情况下访问这些结构的字段
通过这种方式,您可以将它用于多种协议,因此您不仅限于 IPv6 或 IPv4。
所以你可以这样做
struct sockaddr_storage addr;
socklen_t sa_len = sizeof(addr);
recvfrom (sock, buffer, sizeof (buffer), (struct sockaddr*) &addr, &sa_len);
如果您需要知道 sockaddr 的 kinf 是什么,您可以检查每个 sockaddr 结构中存在的强制性 sa_family_t ss_family
字段。
您可能还对此link 或one 感兴趣。
【讨论】:
感谢您提供sockaddr_storage
参考,这真的很有帮助
您对不使用sockaddr_storage
有负面经验或参考吗?我问是因为你提到了它,从那以后我一直像魔鬼一样避免它,唯一的原因是在某些平台上它是一个巨大的结构。 sockaddr_in6
到目前为止一直为我工作,但“一直为我工作”的真正含义是什么......
好吧,据我所知,这是处理多协议案例的好习惯。该标准没有规定所有 sockaddr 结构的大小(不禁止对齐优化,即使它与在线上运行的不同),唯一的规定是 sockadrr_storage 必须足够大以容纳任何其中。【参考方案2】:
您将sockaddr_in6
(类型转换)的指针和sockaddr_in6
结构的大小作为参数传递:
struct sockaddr_in6 in6;
socklen_t len6 = sizeof(in6);
recvfrom(sock, buf, buflen, (struct sockaddr *) &in6, &len6);
由于您将正确的长度传递给函数,因此它将起作用。
【讨论】:
感谢您的回答。我曾经认为最后一个参数是提供给recvfrom
,以便函数用实际的发件人地址填充它。我误会了吗?或者最后一个参数有两个目的:在调用recvfrom
之前指示可用的地址缓冲区大小和调用之后存储实际地址大小?
@Kolyunya 它用于两者。当你调用函数时,你告诉它套接字地址结构有多大,当它返回时,函数将它设置为它用来填充结构的大小。以上是关于如何使用 recvfrom 获取 AF_INET6 套接字的地址的主要内容,如果未能解决你的问题,请参考以下文章