Reputation: 33
I have a sender and a receiver connected with sockets. When the sender sends something, I would like to use the timer on poll() to know if no acknowledgement is coming back from the receiver. After reading a lot of questions (Why does poll keep returning although there is no input?, Embedded Linux poll() returns constantly, poll(2) doesn't empty the event queue) I understand that the poll() function can return 1 even if the receiver didn't send anything back, just because the read() function would not block on the file descriptor of the socket.
But I would like to use the timeout of poll() to know if nothing arrived on the socket. How can I make the poll() function return 1 only if new data has arrived on the socket ?
Here is a sample of my code, in case I'm doing something wrong:
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: this code never prints "Timeout occurred!" because the file descriptor of the socket is always ready. Can I change this behavior?
Upvotes: 1
Views: 5522
Reputation: 29
Looking at the code here, it appears that the call to poll is incorrect.
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
Instead of passing ufds[0].fd + 1
, assuming that there is only one struct in the array, the poll call should be:
rv = poll(ufds, 1, 1000);
As the code reads above, it is probably assuming there is more than one member of the ufds array and reading an invalid pollfd struct causing an invalid return.
Upvotes: 0
Reputation: 4922
The problem is that the file descriptor currently won't block if you write to it. In which case poll returns a positive number. i.e. this poll isn't timing out ever which is why you are never seeing the timeout occurred message. To fix this you need to change the poll call to just look for receive events. You can read about poll here: http://linux.die.net/man/2/poll.
Upvotes: 0
Reputation: 3691
Probably been answered in the linked posts, but the basic idea is that the poll
, select
, and other mechanisms do not tell you when there is new data on the socket. As you mention correctly, they only tell you when a read()
would not block.
You may use EPOLLET
with Linux's epoll(7)
interface (other systems might have other equivalents) to do what you want; however keep in mind this is not portable.
The correct and accepted design is to either consume the network buffer fully, keep partial messages in a application-defined buffer (i.e. not in the socket's buffer) and keep track of how much additional data you need to read from the network.
Upvotes: 1