套接字超时:select 与 setsockopt

Socket timeout: select vs setsockopt

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

What are the differences between these two methods and is there any reason to prefer one implementation over the other both for Linux (Redhat) and Windows?

对于Linux,差异似乎很小:

Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default) then the operation will never timeout. Timeouts only have effect for system calls that perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for select(2), poll(2), epoll_wait(2), and so on.

Source

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

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. If the socket is created using the WSASocket function, then the dwFlags parameter must have the WSA_FLAG_OVERLAPPED attribute set for the timeout to function properly. Otherwise the timeout never takes effect.

Source

因此在超时之后,套接字将无法使用(这可能不是您想要的行为)。 仅出于此行为在两个 Berkely 套接字实现之间不同的唯一原因,我不建议使用 setsockopt(SO_SNDTIMEO/SO_RCVTIMEO),而是使用为此原因创建的设施,例如select,或者更好的是,像 boost::asio.

这样的合适的网络套接字库