仅对套接字上的新数据使用 poll() 超时

问题描述 投票:0回答:3

我有一个通过套接字连接的发送器和接收器。 当发送方发送某些内容时,我想使用 poll() 上的计时器来了解接收方是否没有返回确认。 读了很多问题后(为什么没有输入,poll 却不断返回?嵌入式 Linux poll() 不断返回poll(2) 没有清空事件队列)我明白了 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:此代码永远不会打印“发生超时!”因为socket的文件描述符总是准备好的。我可以改变这种行为吗?

c sockets timeout posix-select
3个回答
1
投票

可能在链接的帖子中得到了回答,但基本思想是

poll
select
和其他机制不会告诉您套接字上何时有新数据。正如您正确提到的,它们告诉您何时
read()
不会阻塞。

您可以将

EPOLLET
与 Linux 的
epoll(7)
界面(其他系统可能有其他等效项)一起使用来完成您想要的操作;但请记住,这不是便携式的。

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


0
投票

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


0
投票

看这里的代码,似乎对 poll 的调用不正确。

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

而不是传递

ufds[0].fd + 1
,假设数组中只有一个结构体,poll 调用应该是:

rv = poll(ufds, 1, 1000);

正如上面的代码所示,它可能假设 ufds 数组有多个成员并读取无效的 pollfd 结构,导致无效返回。

© www.soinside.com 2019 - 2024. All rights reserved.