c++ - 为什么在套接字编程中需要 Value-Result 参数? (需要澄清)

标签 c++ c sockets parameter-passing

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

尽管阅读了无数页面和此处的其他问题,但我仍在努力完全理解值(value)结果论证到底是什么。

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

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

我意识到这个问题可能听起来有些愚蠢,但如果对此有任何澄清就更好了,在此先感谢您。

最佳答案

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

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

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

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

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

关于c++ - 为什么在套接字编程中需要 Value-Result 参数? (需要澄清),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30639056/

相关文章:

c - C语言:如何使用宏作为装饰器?

Java客户端-服务器不重复响应

c++ - 声明一个以类构造函数作为函数参数的函数

c++ - 如何避免包含需要 BOOST 序列化的每个类的 header ?

c - C语言从键盘读取字符串

c - 在夹板的帮助下消除代码中的安全缺陷

sockets - 如何从主机向运行在 docker 容器中的子套接字发送消息?

perl - 通过套接字进行 3 路通信

c++ - OpenCV 视频捕获 : Howto get specific frame correctly?

c++ - 查找两者之间的两个数字的正则表达式的匹配