【问题标题】:Socket timeout: select vs setsockopt套接字超时:select vs setsockopt
【发布时间】:2021-08-25 04:04:51
【问题描述】:

我正在使用超时在套接字上发送和接收数据。我发现可以通过将套接字设置为非阻塞模式并使用select 或使用setsockoptSO_SNDTIMEO/SO_RCVTIMEO 选项来实现超时。
这两种方法之间有什么区别?对于 Linux (Redhat) 和 Windows,是否有任何理由偏爱一种实现方式而不是另一种实现方式?

【问题讨论】:

标签: c++ sockets winsock


【解决方案1】:

这两种方法之间有什么区别?在 Linux (Redhat) 和 Windows 上,是否有任何理由偏爱一种实现方式而不是另一种实现方式?

对于 Linux,差异似乎很小:

指定接收或发送超时直到报告错误。参数是 struct timeval。如果输入或输出函数在这段时间内阻塞,并且数据已经发送或接收,则该函数的返回值将是传输的数据量;如果没有数据传输并且已经达到超时,则返回 -1,并将 errno 设置为 EAGAIN 或 EWOULDBLOCK,或 EINPROGRESS(对于 connect(2))就像指定套接字是非阻塞的一样。如果超时设置为零(默认值),则操作将永远不会超时。超时仅对执行套接字 I/O 的系统调用有效(例如 read(2)、recvmsg(2)、send(2)、sendmsg(2));超时对 select(2)、poll(2)、epoll_wait(2) 等无效。

Source

但是,您没有方便的属性来同时多路复用多个连接,例如使用select。 对于 Windows,差异更为严重:

阻塞发送调用的超时时间,以毫秒为单位。默认为 此选项为零,表示发送操作不会 暂停。如果阻塞发送调用超时,连接处于 不确定的状态,应该关闭。如果创建了套接字 使用 WSASocket 函数,则 dwFlags 参数必须具有 WSA_FLAG_OVERLAPPED 属性设置为超时运行 适当地。否则超时永远不会生效。

Source

所以超时后,套接字将无法使用(这可能不是您想要的行为)。 由于两个 Berkely 套接字实现之间这种行为不同的唯一原因,我不建议使用 setsockopt(SO_SNDTIMEO/SO_RCVTIMEO),而是使用为此原因创建的工具,例如select,或者更好的是,一个合适的网络套接字库,比如 boost::asio。

【讨论】:

  • 如果发送超时,连接可能在所有平台上都处于“不确定状态”,但关闭它不是强制性的。它可能在接收方向上仍然可以正常工作。
  • @user207421 不,这在 Winsock 的情况下是不正确的,正如我的回答引用中所述。违背 MSDN 的建议当然是一个非常糟糕的主意。
猜你喜欢
  • 2018-09-17
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多