C poll()无限期等待,但指定了超时
我正在编写一个C客户机-服务器程序,其中客户机必须从服务器接收大量数据。由于我希望我的客户机不要在服务器出现问题时无限期地等待C poll()无限期等待,但指定了超时,c,server,client,polling,unix-socket,C,Server,Client,Polling,Unix Socket,我正在编写一个C客户机-服务器程序,其中客户机必须从服务器接收大量数据。由于我希望我的客户机不要在服务器出现问题时无限期地等待recv()(例如,在发送数据时停止),因此我选择使用中指定的poll()函数 我的代码如下所示: while (...) { struct pollfd fds; fds.fd = sock; fds.events = POLLIN; retry: r = poll(&fds, 1, TIMEOUT*1000); if (r == -1 &
recv()
(例如,在发送数据时停止),因此我选择使用中指定的poll()
函数
我的代码如下所示:
while (...)
{
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
retry:
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1 && errno == EINTR)
goto retry;
else if (r == -1)
err_sys("poll() failed");
else if (r == 0)
err_sys("timeout expired");
recv(...)
}
其中,sock
是与套接字关联的文件描述符,TIMEOUT
设置为5秒,我指定POLLIN
作为事件,因为我对读取数据感兴趣
问题
据曼恩说:
timeout参数指定轮询()的毫秒数
应阻止等待文件描述符就绪。电话
将阻止,直到:
(1) a file descriptor becomes ready;
(2) the call is interrupted by a signal handler; or
(3) the timeout expires.
但是,程序会无限期地阻塞poll()
函数,即使我一停止服务器超时(我使用了valgrind)。我还尝试将事件设置为POLLIN | POLLPRI
(以捕获一些异常情况),但没有成功。我多次阅读文档,无法找出导致此问题的原因
其他信息
我使用的是Xubuntu 18.04,gcc版本7.4.0,目标x86_64您的代码无条件地调用
recv()
,即使没有数据可读取。事实上,如果poll()
没有返回错误/超时,则完全忽略了fds.revents
字段
您的循环应该更像这样:
struct pollfd fds;
fds.fd = sock;
fds.events = POLLIN;
do {
r = poll(&fds, 1, TIMEOUT*1000);
if (r == -1) {
if (errno == EINTR) continue;
perror("poll() failed");
break;
}
else if (r == 0) {
printf("timeout expired");
break;
}
else if (fds.revents & POLLIN) {
r = recv(...);
if (r < 0) {
perror("recv() failed");
break;
}
else if (r == 0) {
printf("socket disconnected\n");
break;
}
else {
// process data as needed...
}
}
else if (fds.revents & (POLLERR | POLLNVAL)) {
printf("socket error\n");
break;
}
}
while (1);
close(sock);
struct pollfd fds;
fds.fd=袜子;
fds.events=POLLIN;
做{
r=轮询(&fds,1,超时*1000);
如果(r==-1){
如果(errno==EINTR)继续;
perror(“poll()失败”);
打破
}
else如果(r==0){
printf(“超时过期”);
打破
}
否则如果(fds.revents&POLLIN){
r=recv(…);
if(r<0){
perror(“recv()失败”);
打破
}
else如果(r==0){
printf(“套接字断开连接\n”);
打破
}
否则{
//根据需要处理数据。。。
}
}
否则如果(fds.revents和(POLLERR | POLLNVAL)){
printf(“套接字错误\n”);
打破
}
}
而(1),;
关闭(袜子);
通过strace
运行程序?为什么使用goto
而不是正常的do/while
循环?请阅读,因为您只发布了一段代码,很难理解示例代码(没有sock
的声明只给出了,而循环没有精确的测试表达式,并且没有对poll
系统调用进行完整的错误检查。)非常感谢,伙计!我假设在fds.events
中设置POLLIN
标志,recv
的返回值不能为0,因为总是有数据要读取。