【问题标题】:Using timeouts on socket send() and recv() [closed]在套接字 send() 和 recv() 上使用超时 [关闭]
【发布时间】:2016-04-04 12:50:01
【问题描述】:

总是使用 select() 或 poll() 并在 send() 和 recv() 调用上施加 10 秒超时是个好主意吗?还是我应该让他们无限期地阻止?

施加这种超时(使用 select() 或 poll())是否会导致我失去某种错误报告或功能(以返回值的形式),而我只使用 send() 和 recv 时可以获得的()?

注意:假设我在调用 recv() 或 send() 之前在同一个线程中轮询。并且对 poll() 的调用是静态格式良好的,即参数不会动态变化,除了它们如何基于包装的 recv() 或 send() 的调用

另一个注意事项:如果有超时,那么我将抛出一个异常并让程序员捕捉它。我希望这可以防止 DOS 攻击。如果确实有超时。我会抛出一个异常,而不是调用 recv() 或 send()

还有一个注意事项:与我正在谈论的内容相关的源代码可以在此处https://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#faq 在类似的常见问题解答下找到

谢谢!

【问题讨论】:

  • 您到底想解决什么问题?如果出现超时,你会怎么做?重新开始投票?还是退出?或者是其他东西?如果出现其他错误,您希望做什么?如果接收方确实处于“慢速”状态并且消息正在到达那里,但速度非常慢(例如,有人用慢得多的链接替换了快速链接),您希望发生什么?
  • 你能提供一些代码吗?
  • DOS 攻击通常是“大量流量”,而不是“无流量”,这就是超时...
  • 我在上面编辑了我的问题!很抱歉第一次不够清楚..
  • @MatsPetersson 是的,你是对的!但我想到的攻击类型是当我等待 recv() 时,我应该在逻辑上获取更多数据,因为到目前为止的请求是不完整的,攻击者只是坐在那里不发送任何数据。

标签: c++ c sockets network-programming tcpsocket


【解决方案1】:

select() 和 poll() 只是告诉你准备好读取哪些文件描述符。一旦您知道哪些文件描述符已准备就绪,您仍然可以在它们上调用 recv() ,这样您将获得相同的返回值/错误检查。

如果您有多个要读取的套接字/文件描述符,您实际上只需要使用 select() 或 poll()。如果您只需要单个套接字上的超时,那么您可以使用带有 SO_RCVTIMEO 选项的 setsockopt() 来允许 recv() 调用超时。见this answer

【讨论】:

  • poll 比 SO_RCVTIMEO 的优势在于超时是站点可配置的。不过,这个答案很好。
【解决方案2】:

超时后你打算做什么?如果您要再次开始等待,那么超时不会给您任何帮助。

如果您要关闭连接并将其标记为死,那么超时非常有用。

【讨论】:

  • 如果我打算抛出一个异常说发生了超时,这是个好主意吗?
  • @Curious,我不知道。在您的应用程序中这是一个好主意吗?超时是一个例外情况,您在调用站点绝对不能容忍它,也不能理智地向上游传播错误?
  • 我还没有想到任何应用程序,但我只是觉得每个 recv 调用在实际场景中使用时都应该有某种超时,对吧?
  • @Curious,有很多应用程序不处理任何超时,只是等待数据或连接中断。
  • 普通的 HTTP 服务器怎么样?这样的服务器中的 recv() 调用应该有这样的超时时间吗?
【解决方案3】:

如果您在同步方法中使用套接字,那么您必须使用超时。但是更好但更难的方法是使用它们 asyncron。所以,在他们自己的线程中运行,他们可以阻塞并且将使用最少的资源......

【讨论】:

  • 一般回答不好。在许多情况下,完全不需要在单独的线程中执行套接字操作。
【解决方案4】:

对以“总是好主意”开头的问题的回答通常是“否”。在这里,答案取决于您poll() 的方式,所以不,这并不总是一个好主意。

如果您 poll() 在一个单独的线程中,其目标是等待数据,超时不会做任何事情。

【讨论】:

  • 假设我在调用 recv() 或 send() 之前在同一个线程中轮询。并且对 poll() 的调用是静态格式良好的,即参数不会动态变化,除了它们如何基于包装的 recv() 或 send()/ 的调用
最近更新 更多