Answers:
您可以使用setsockopt函数来设置接收操作的超时:
SO_RCVTIMEO
设置超时值,该值指定输入函数完成之前等待的最长时间。它接受一个timeval结构,该结构的秒数和微秒数指定了等待输入操作完成的时间限制。如果接收操作阻塞了这么长时间而没有接收到其他数据,则如果没有接收到数据,它将以部分计数或errno设置为[EAGAIN]或[EWOULDBLOCK]返回。此选项的默认值为零,表示接收操作不应超时。此选项采用timeval结构。请注意,并非所有实现都允许设置此选项。
// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
据说在Windows上应该在调用之前完成bind
。我已经通过实验验证了它可以bind
在Linux和OS X 之前或之后完成。
struct timeval tv;
那是否意味着select()也无法正常工作?我试图将我的select()代码移植到Windows,它只是立即超时,似乎忽略了我在timeval设置的值。
这是一些简单的代码,可以在C中recv
使用超时功能poll
:
struct pollfd fd;
int ret;
fd.fd = mySocket; // your socket handler
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
case -1:
// Error
break;
case 0:
// Timeout
break;
default:
recv(mySocket,buf,sizeof(buf), 0); // get your data
break;
}
poll
将等待接收至少一个字节或超时,而在调用该recv
函数时将等待sizeof(buf)
字节,如果尚未达到此计数(但这次没有超时),将导致它再次阻塞。
安装的处理程序SIGALRM
,然后在常规阻止之前使用alarm()
或。如果警报响起,将会返回错误,其设置为。ualarm()
recv()
recv()
errno
EINTR
LINUX
struct timeval tv;
tv.tv_sec = 30; // 30 Secs Timeout
tv.tv_usec = 0; // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));
视窗
DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
注意:您已将此设置放在bind()
函数调用之前以正确运行