繁体   English   中英

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

[英]How to send and receive data up to SO_SNDTIMEO and SO_RCVTIMEO without corrupting connection?

我目前正在计划如何在中间网络应用程序中为TCP服务器开发人员,以便在服务器和客户端之间传输数据。 它将充当服务器的常规客户端和服务器的远程客户端,而无需修改任何数据。 在连接处于非活动状态时,可以选择使用它来检测和测量服务器或客户机无法接收准备接收的数据的时间。

我打算使用阻止发送和接收功能。 在进行任何数据传输之前,我将调用setsockopt函数将SO_SNDTIMEO和SO_RCVTIMEO设置为大约10到20毫秒,假设它将强制阻塞send和recv函数提早返回,以便路由另一个活动的连接数据。 每个连接的运行线程看起来太昂贵。 我不会在这里使用异步套接字,因为我无法保证它们会在几分之一秒内完成,特别是在发送或接收大量数据时。 高数据延迟看起来不太好。 我会在这里使用很小的缓冲区,但是为每个接收到的字节调用函数看起来过于浪费。

我的下一个假设是,如果之前已因超时而终止并且收到的数据少于请求的数量,则可以稍后再调用send或recv。

但是我对msdn上可用的信息感到矛盾而感到困惑。

发送功能

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

如果未发生错误,则send返回已发送的字节总数,该总数可以小于len参数中请求发送的字节数。


SOL_SOCKET套接字选项

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

SO_SNDTIMEO-阻止发送呼叫的超时(以毫秒为单位)。 此选项的默认值为零,表示发送操作不会超时。 如果阻塞的发送呼叫超时,则连接处于不确定状态,应将其关闭。

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

谢谢答案

当您可以按照问题中给出的想法实施某些操作时,在所有主要系统上都有更可取的替代方法。

即:

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

使用这些技术,您可以处理多个套接字上的流量,而无需超时逻辑并以有效的反应方式进行轮询。 它们都可以视为套接字API中古老的select()函数的后继者。

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

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

在连接上转发数据的基本方法是:在知道可以将数据发送到传出套接字之前,不要从传入套接字中读取数据。 如果您贪婪地阅读(并在应用程序层上缓冲),则会使通信通道失去其反压机制。

因此,基本上,“发送能力”应该驱动接收动作。

对于此“中间人”使用超时,有两种主要方案:

  1. 您知道发送方应用程序的发送行为。 即是否有意在任何时候在您选择的接收超时时间内发送任何数据。 某些应用程序仅偶尔发送,接收超时的任何选定值都可能是错误的。 即使应该在特定的时间间隔发送,一旦有人调试了发送应用程序,超时也会给您带来麻烦。
  2. 您希望“中间人”适用于未知的应用程序(当然,中间人一定不能使用某种加密方法)。 在那里,您无法选择任何“足够的”超时值,因为您对所涉及的应用程序的发送行为一无所知。

正如先前的海报所建议的那样,我强烈建议您重新考虑服务器的设计,以使其采用异步I / O策略。 这很可能需要您花费大量时间来学习每种操作系统的首选方法。 这将是度过的时间。

对于除玩具应用程序以外的任何其他应用程序,以您建议的方式使用阻塞I / O都不能很好地执行。 即使超时很短,在我看来,在完成当前连接的工作之前,您将无法为新连接提供服务。 您可能还会发现(短时超时)正在花费更多的CPU时间来等待工作而不是实际工作。

以前的海报明智地建议您看一下Windows I / O完成端口。 看看我2007年为Dobbs博士写的这篇文章。 这不是完美的,但是我尝试做一个不错的工作来解释如何设计一个使用小线程池来处理潜在大量连接的简单服务器:

Windows I / O完成端口http://www.drdobbs.com/cpp/multithreaded-asynchronous-io-io-comple/201202921

如果您使用的是Linux / FreeBSD / MacOSX,请查看libevent:

Libevent http://libevent.org/

最后,一本关于编写TCP / IP服务器和客户端的实用书籍,是Michael Donahoe和Kenneth Calvert撰写的“ C中的实用TCP / IP套接字”。 您还可以查看W. Richard Stevens的文本(完整涵盖了UNIX主题。)

总而言之,我认为您应该花一些时间来了解有关异步套接字I / O和用于服务器开发的已建立的最佳方法的更多信息。

如果您有疑问,请随时私下给我发消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM