首页 文章

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

提问于
浏览
1

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

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

我的下一个假设是,如果以前通过超时终止并且收到的数据少于请求,则可以安全地调用send或recv .

但我对msdn提供的信息存在矛盾感到困惑 .

发送功能https://msdn.microsoft.com/en-us/library/windows/desktop/ms740149%28v=vs.85%29.aspx如果没有发生错误,send返回发送的总字节数,可以小于请求在len参数中发送的数量 .


SOL_SOCKET套接字选项https://msdn.microsoft.com/en-us/library/windows/desktop/ms740532%28v=vs.85%29.aspx SO_SNDTIMEO - 阻止发送呼叫的超时(以毫秒为单位) . 此选项的默认值为零,表示发送操作不会超时 . 如果阻塞发送呼叫超时,则连接处于不确定状态,应该关闭 .

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

谢谢你的回答

2 回答

  • 3

    虽然您可能会在您的问题中实现某些想法,但在所有主要系统上都有更好的选择 .

    即:

    在FreeBSD和家庭上

    • kqueue . 在MAC OSX上 .

    • epoll on linux及相关类型的操作系统 .
      Windows上

    • IO完成端口 .

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

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

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

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

    所以基本上,“发送功能”应该驱动接收动作 .

    至于使用这个“中间人”的超时,有两个主要场景:

    • 您知道发件人应用程序的发送行为 . 即如果它有意在任何时间在您选择的接收超时内发送任何数据 . 某些应用程序只是偶尔发送,任何选定的接收超时值都可能是错误的 . 即使它应该以特定的时间间隔发送,一旦有人调试发送应用程序,您的超时将导致麻烦 .

    • 您希望"middle man"适用于未知应用程序(当然,中间人不能使用某些加密技术) . 在那里,您不能选择任何"adequate"超时值,因为您对所涉及的应用程序的发送行为一无所知 .

  • 3

    作为以前的海报有建议,我强烈建议您重新考虑服务器的设计,以便它采用异步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以及用于开发服务器的已 Build 的最佳方法的更多信息 .

    如果您有任何疑问,请随时向我发送私信 .

相关问题