Linux:有没有超时套接字读取或recv?
我怎样才能尝试从套接字超时读取数据? 我知道,select,pselect,poll,有一个超时字段,但是使用它们会禁用tcp reno栈中的“tcp fast-path”。
我唯一的想法是在循环中使用recv(fd,…,MSG_DONTWAIT)
您可以使用setsockopt函数设置接收操作的超时时间:
SO_RCVTIMEO
设置指定input函数等待完成的最长时间的超时值。 它接受一个timeval结构,秒数和微秒数指定了等待input操作完成的时间限制。 如果接收操作在没有接收到附加数据的情况下被阻塞了这么多时间,如果没有收到数据,它应该返回一个部分计数或错误设置为[EAGAIN]或[EWOULDBLOCK]。 此选项的默认值为零,表示接收操作不应超时。 该选项采用timeval结构。 请注意,并非所有实现都允许设置此选项。
// 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)); // WINDOWS DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000; setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
这里有一个简单的代码来添加时间到您的recv函数使用轮询在C:
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; }
为SIGALRM
安装一个处理程序,然后在定期阻塞recv()
之前使用alarm()
或ualarm()
recv()
。 如果警报closures,则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()
函数调用之前,以便正确运行