【问题标题】:How to get an addres of AF_INET6 socket with recvfrom如何使用 recvfrom 获取 AF_INET6 套接字的地址
【发布时间】: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,我是否理解正确,该函数将无法知道有足够的空间来存储地址?

【问题讨论】:

    标签: c++ c linux sockets ip-address


    【解决方案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 字段。

    您可能还对此linkone 感兴趣。

    【讨论】:

    • 感谢您提供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 它用于两者。当你调用函数时,你告诉它套接字地址结构有多大,当它返回时,函数将它设置为它用来填充结构的大小。
    猜你喜欢
    • 2015-05-23
    • 1970-01-01
    • 2011-09-02
    • 2019-03-24
    • 1970-01-01
    • 2015-01-09
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多