我正在开发 UDP 服务器/客户端应用程序。
为了查明是否有客户端宕机,服务器向客户端发送握手消息。然后,服务器等待客户端的响应以发送一些数据以确保客户端处于活动状态。为此,服务器会阻塞对
recvfrom()
的调用,除非客户端回复,但如果客户端宕机,服务器会无限期阻塞对 recvfrom()
的调用。
我想在我的服务器上实现这样的功能,以便它在对
recvfrom()
的调用中等待特定时间(例如 2 秒)。如果2秒内没有收到客户端的数据,则认为客户端已死亡,recvfrom()
返回。
有什么办法可以做到吗?我搜索了互联网,但找到了诸如设置
MSG_DONTWAIT
标志之类的解决方案,该标志在没有收到数据时立即返回,但就我而言,我不希望 recvfrom()
立即返回,而是等待数据一段特定的时间,并且当没有收到数据时如果在该特定持续时间内收到数据,则 recvfrom()
函数应该返回。
最简单的方法是使用
setsockopt()
为相关套接字设置接收超时。
SO_RCVTIMEO
用于此目的。
如果为传递给
recvfrom()
的套接字设置了超时,如果没有收到数据,则该函数会在超时后返回。
例如,设置 10 μs 读取超时(根据需要对
setsockopt()
返回的值添加错误检查):
#include <sys/types.h>
#include <sys/socket.h>
...
struct timeval read_timeout;
read_timeout.tv_sec = 0;
read_timeout.tv_usec = 10;
setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof read_timeout);
有关详细信息,在 Windows 上请参阅此处,在 Linux 上请参阅此处和/或此处 (POSIX)。
注意!上述解决方案的示例适用于 Linux。相同的操作相同的常量在windows下是不同的!!我搜索了一段时间后,在 stackoverflow: set-timeout-for-winsock-recvfrom 中发现了一个小提示,没有错误消息,没有警告。 Windows 的解决方案是:
DWORD read_timeout = rxTimeout_us/1000; // it is milliseconds!
error = setsockopt(so.socket, SOL_SOCKET, SO_RCVTIMEO, (char const*)&read_timeout, sizeof read_timeout);