问题描述
我使用超时在套接字上发送和接收数据。我发现超时可以通过将套接字设置为非阻塞模式并使用 select
或使用 setsockopt
和 SO_SNDTIMEO
/SO_RCVTIMEO
选项来实现。
这两种方法之间有什么区别,对于 Linux (Redhat) 和 Windows,是否有任何理由更喜欢一种实现而不是另一种实现?
解决方法
这两种方法之间有什么区别,对于 Linux (Redhat) 和 Windows,是否有任何理由更喜欢一种实现而不是另一种实现?
对于 Linux,差异似乎相当小:
指定接收或发送超时直到报告错误。参数是一个结构体 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) 等没有影响。
但是,您没有方便的属性来同时多路复用多个连接,例如, select
。
对于 Windows,差异更为严重:
阻塞发送调用的超时时间,以毫秒为单位。默认为 此选项为零,表示发送操作不会 超时。如果阻塞发送调用超时,连接处于 不确定状态,应关闭。如果创建了套接字 使用 WSASocket 函数,则 dwFlags 参数必须具有 WSA_FLAG_OVERLAPPED 属性设置为超时功能 适当地。否则超时永远不会生效。
因此超时后,套接字将无法使用(这可能不是您想要的行为)。
唯一的原因是这种行为在两个 Berkely 套接字实现之间有所不同,我不建议使用 setsockopt(SO_SNDTIMEO/SO_RCVTIMEO)
,而是使用为此而创建的工具,例如select
,或者更好的是像 boost::asio 这样的合适的网络套接字库。