仅对socket上的新数据使用poll()超时

时间:2014-10-22 21:23:00

标签: c sockets select timeout

我有一个发送器和一个接收器连接套接字。 当发送者发送内容时,我想在poll()上使用定时器来知道是否没有来自接收者的确认。 在阅读了很多问题后(Why does poll keep returning although there is no input?Embedded Linux poll() returns constantlypoll(2) doesn't empty the event queue)我明白了poll()函数可以返回1,即使接收者没有发回任何东西,只是因为read()函数不会阻塞套接字的文件描述符。

但我想使用poll()的超时来知道套接字上是否有任何内容。 如果新数据已经到达套接字,我怎样才能使poll()函数返回1?

以下是我的代码示例,以防我做错了什么:

while(1){

        rv = poll(ufds, ufds[0].fd +1 , 1000);

        if (rv == -1) {
            perror("poll"); 
        } else if (rv == 0) {
            printf("Timeout occurred!  No data after 1 seconds.\n");
        } else {
            if (ufds[0].revents & POLLIN) {
                if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1)
                {
                    die("recvfrom()");
                }
                printf("ACK =  %s \n", buf);
            }
            if (ufds[0].revents & POLLPRI) {
                if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1)
                {
                    die("recvfrom()");
                }
            }
        }
    }

TL; DR:此代码从不打印“超时发生!”因为套接字的文件描述符总是准备好的。我可以改变这种行为吗?

非常感谢!

3 个答案:

答案 0 :(得分:1)

可能已在链接的帖子中得到解答,但基本的想法是pollselect和其他机制不会告诉您套接字上有新数据。正如您所提到的,他们告诉您何时read()不会阻止。

您可以将EPOLLET与Linux的epoll(7)接口(其他系统可能具有其他系统)一起使用,以执行您想要的操作;但请记住,这不是便携式的。

正确且可接受的设计是完全使用网络缓冲区,将部分消息保存在应用程序定义的缓冲区中(即在套接字缓冲区中)并跟踪你有多少额外数据需要从网络上阅读。

答案 1 :(得分:0)

问题是如果您写入文件描述符当前不会阻止。在这种情况下,轮询返回正数。即,此轮询不会超时,这就是为什么你永远不会看到超时发生的消息。要解决此问题,您需要更改轮询调用以查找接收事件。您可以在此处阅读有关民意调查的信息:http://linux.die.net/man/2/poll

答案 2 :(得分:0)

看看这里的代码,看来轮询调用是不正确的。

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

假定数组中只有一个结构,而不是传递ufds[0].fd + 1,轮询调用应该是:

rv = poll(ufds, 1, 1000);

如上面的代码所示,很可能是假设ufds数组中有多个成员并且读取了一个无效的pollfd结构,从而导致无效的返回。