c++ - 如何在不破坏连接的情况下发送和接收 SO_SNDTIMEO 和 SO_RCVTIMEO 的数据?

标签 c++ c sockets network-programming

我目前正在计划如何为 TCP 服务器开发一个中间人网络应用程序,该应用程序将在服务器和客户端之间传输数据。它将作为服务器的常规客户端和远程客户端的服务器而不修改任何数据。它将可选地用于检测和测量服务器或客户端在连接不活动的情况下无法接收准备接收的数据的时间。

我打算使用阻塞发送和接收函数。在任何数据传输之前,我会调用 setsockopt 函数将 SO_SNDTIMEO 和 SO_RCVTIMEO 设置为大约 10 - 20 毫秒,假设它将强制阻止发送和接收函数提前返回,以便让另一个事件连接数据被路由。每个连接运行线程看起来太昂贵了。我不会在这里使用异步套接字,因为我无法保证它们会在几分之一秒内完成,尤其是在发送或接收大量数据时。高数据延迟看起来不太好。我会在这里使用非常小的缓冲区,但为每个接收到的字节调用函数看起来有点过分了。

我的下一个假设是,如果之前因超时而终止并且收到的数据少于请求的数据,则稍后调用发送或接收是安全的。

但我对 msdn 上提供的相互矛盾的信息感到困惑。

send function

https://msdn.microsoft.com/en-us/library/windows/desktop/ms740149%28v=vs.85%29.aspx

If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter.


SOL_SOCKET Socket Options

https://msdn.microsoft.com/en-us/library/windows/desktop/ms740532%28v=vs.85%29.aspx

SO_SNDTIMEO - The timeout, in milliseconds, for blocking send calls. The default for this option is zero, which indicates that a send operation will not time out. If a blocking send call times out, the connection is in an indeterminate state and should be closed.

我的假设是否正确,我可以像这样使用这些功能?也许有更有效的方法来做到这一点?

感谢解答

最佳答案

虽然您可能会按照您在问题中给出的想法实现某些操作,但在所有主要系统上都有更好的选择。

即:

  • 在 FreeBSD 和家族上使用 kqueue。在 MAC OSX 上。
  • 在 Linux 和相关类型的操作系统上执行 epoll。
  • Windows 上的 IO 完成端口。

使用这些技术,您可以在没有超时逻辑的情况下处理多个套接字上的流量,并以高效、 react 性的方式进行轮询。它们都可以被认为是套接字 API 中古老的 select() 函数的继承者。

至于在您的问题中引用的 send() 文档,它并没有真正令人困惑或矛盾。有用的网络协议(protocol)实现了一种机制,以在发送方尝试发送比接收方(和/或传输 channel )可以容纳的更多数据的情况下创建“背压”。因此,如果网络堆栈已为它准备好缓冲区空间,应用程序只能向 send() 提供更多数据。

例如,如果一个应用程序试图发送 3Kb 的数据,而 tcp/ip 堆栈只有 800 字节的空间,send() 可能会成功并返回它使用了 800 字节的数据3k 提供字节。

在连接上转发数据的基本方法是:在知道可以将数据发送到传出套接字之前,不要从传入套接字读取数据。如果你贪婪地阅读(并在应用层缓冲),你就剥夺了通信 channel 的背压机制。

所以基本上,“发送能力”应该驱动接收操作。

至于为这个“中间人”使用超时,主要有两种情况:

  1. 您知道发件人应用程序的发送行为。 IE。如果它有意随时在您选择的接收超时范围内发送任何数据。一些应用程序只是偶尔发送,并且任何选择的接收超时值都可能是错误的。即使它应该以特定的时间间隔发送,一旦有人调试发送应用程序,您的超时也会造成麻烦。
  2. 您希望“中间人”为未知应用程序工作(当然,中间人必须不使用某些加密才能有机会)。在那里,您无法选择任何“足够”的超时值,因为您对相关应用程序的发送行为一无所知。

关于c++ - 如何在不破坏连接的情况下发送和接收 SO_SNDTIMEO 和 SO_RCVTIMEO 的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29520523/

相关文章:

c++ - 共享头文件的正确命名是什么

谁能解释一下这个程序发生了什么

c# - 最长递增子序列的数量

mongodb - Nodejs - websocket-node 模块 : How to make multi-client socket-server works?

c - 当虚拟内存使用量达到256GB时进程输入界面停止响应

c++ - ShellExecute Format DOS 命令

c++ - 如果 npos 为 -1,size_type 怎么可能是无符号整数?

node.js - 实用或最佳的 socket.io 实现

c# - 从 Win32 或 C# API 获取窗口安静时间

c++ - Float 和 Double 值在 c 中造成困惑