我有一个发送器和一个接收器连接套接字。 当发送者发送内容时,我想在poll()上使用定时器来知道是否没有来自接收者的确认。 在阅读了很多问题后(Why does poll keep returning although there is no input?,Embedded Linux poll() returns constantly,poll(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:此代码从不打印“超时发生!”因为套接字的文件描述符总是准备好的。我可以改变这种行为吗?
非常感谢!
答案 0 :(得分:1)
可能已在链接的帖子中得到解答,但基本的想法是poll
,select
和其他机制不会告诉您套接字上有新数据。正如您所提到的,他们仅告诉您何时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结构,从而导致无效的返回。