【问题标题】:Why do we need Value-Result arguments in socket programming? (Clarification required)为什么我们在套接字编程中需要 Value-Result 参数? (需要澄清)
【发布时间】:2015-08-18 18:46:33
【问题描述】:

当被问到诸如“什么是值-结果参数以及为什么在套接字编程中需要它?”之类的问题时,我有点困惑。

尽管在这里阅读了无数页和其他问题,但我仍在努力完全理解价值结果论点的确切含义。

我的理解是,在值结果参数中,内核能够更改传递的参数(因为我们给它一个引用/指针,而不仅仅是它的值)并将其返回给调用的进程/函数它。它既是函数被调用时的“值”(例如告诉内核结构的大小,所以它不会写太多),也是函数返回时的结果(我们在结构中实际写了多少)。

我很难回答,为什么这在套接字编程中如此重要?特别是,当我们处理 sockaddr 结构并传递它们的引用 AND 大小时,即 accept()

我意识到这个问题可能听起来有些愚蠢,但任何对此的澄清都会很好,所以提前致谢。

【问题讨论】:

  • 这个问题有点奇怪——我不明白为什么需要这样的论点——而“套接字编程”是一个相当宽泛的术语。你有没有考虑过问那些问你这些问题的人是什么意思?
  • 唉,它们目前不可用。例如方法 accept() 是值结果,我应该添加它。
  • 我找到了另一个可以回答您问题的线程。有人可以关闭重复:stackoverflow.com/questions/15168095/…

标签: c++ c sockets parameter-passing


【解决方案1】:

您对什么值结果参数有正确的理解。您将输入值分配给变量并通过引用传递它,以便函数可以使用输出值修改变量。这样就不必为输出传递单独的参数,或更改函数返回值的语义。

sockaddr 参数所需的原因是因为不同的传输实现不同的sockaddr_... 结构,这些结构具有不同的大小和布局(sockaddr_in 用于 IPv4,sockaddr_in6 用于 IPv6, sockaddr_un 用于 UNIX 域套接字等)。大多数平台还提供了sockaddr_storage 结构的实现,它大到足以容纳所有其他sockaddr_... 结构,并且在编写多传输代码时很有用。

因此,对于accept(),您必须传入将接收客户端sockaddr_... 的缓冲区的完整大小。当新客户端到达时,accept() 将验证缓冲区是否足够大,可以在填充缓冲区之前接收客户端的实际 sockaddr_... 数据,并返回实际填充了多少缓冲区。

例如,如果您知道套接字仅支持 IPv4(创建为 AF_INET-family 套接字),那么您可以使用 sockaddr_in 作为缓冲区,sizeof(sockaddr_in) 作为缓冲区大小,或者您可以使用sockaddr_storage 作为缓冲区,sizeof(sockaddr_storage) 作为缓冲区大小。在任何一种情况下,accept() 都将使用sockaddr_in 填充缓冲区并将缓冲区大小返回为sizeof(sockaddr_in)。与纯 IPv6 套接字(创建为 AF_INET6-family 套接字)相同,只是用 sockaddr_in6 代替。

现在,假设您有一个支持 IPv4 和 IPv6 的双栈套接字(禁用了 IPV6_V6ONLY 选项的 AF_INET6-family 套接字)。您可以使用 sockaddr_storage 作为缓冲区,sizeof(sockaddr_storage) 作为缓冲区大小,accept() 将使用 sockaddr_insockaddr_in6 填充缓冲区并返回适当的缓冲区大小,具体取决于 IPv4 还是IPv6 客户端被接受。然后,您可以读取sockaddr_storagess_family 字段并将数据类型转换为sockaddr_in(用于AF_INET)或sockaddr_in6(用于AF_INET6)。

【讨论】:

  • 非常感谢,这更有意义!尤其是在缓冲区填充了适当的协议结构时支持 IPv4 和 V6。非常感谢:)
猜你喜欢
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 2012-07-18
  • 1970-01-01
相关资源
最近更新 更多