Jytug
Jytug

Reputation: 1116

poll() doesn't seem to see events on an UDP socket

I'm trying to write a web program, using poll(). I'm creating a UDP in a struct pollfd array, and then polling it. However, the poll() returns 0 every time, no matter how many times I send it a message. When I just call recvfrom, it works just fine. So here's my code:

Creating and binding the socket:

struct pollfd[2] fds;
// ...
fds[0].fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fds[0].fd < 0)
    syserr("socket");
listen_address = { 0 };
listen_address.sin_family = AF_INET;
listen_address.sin_addr.s_addr = htonl(INADDR_ANY); 
listen_address.sin_port = htons(m_port);
if (bind(
        fds[0].fd,
        (struct sockaddr*) &listen_address,
        (socklen_t) sizeof(listen_address)
        ) < 0)
    syserr("bind");

Now this works:

for (;;) {
    memset(buffer, 0, BUF_SIZE + 1);
    rval = recvfrom(
        fds[0].fd,
        buffer,
        BUF_SIZE,
        0,
        (struct sockaddr *) &respond_address,
        &rcva_len
        );
    std::cout << buffer << std::endl;
}

But this doesn't

finished = false;
do {
    fds[0].revents = fds[1].revents = 0;
    ret = poll(fds, 2, 0);
    if (ret < 0) {
        perror("poll");
    } else if (ret == 0) {
        // the loop always enters here
    } else {
        // the loop never enters here,
        // even though I send messages to the socket
    }
} while (!finished);

For testing, I use a command like this

echo -n “foo” | nc -4u -w1 <host> <udp port>

I would appreciate some insight

Upvotes: 0

Views: 1278

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118425

There are two critical problems with the way that you use poll():

  1. You must set the revents field, for each file descriptor, to indicate which events you are interested in, such as POLLIN and/or POLLOUT. Your code fails to set revents to anything.

  2. The third parameter to poll() is the timeout setting. Which you are setting to 0. This means "check the file descriptors for whether or not any of the requested events have occured, but always return immediately in any case, and if no file descriptors have the requested events then return 0".

Which is the behavior you are seeing.

Instead of telling you what you need to set the third parameter to, in order to wait until any of the file descriptors's events have occured, I'll just refer you to poll()'s manual page. Reading manual pages is good. They explain everything.

In conclusion:

  1. Initialize each file descriptor's revents parameter properly.

  2. Pass the correct parameters to poll(), as described in its manual page. If you want poll() to wait indefinitely, until any of the passed file descriptors' requested events have occured, there's a specific value to do this. Look it up.

  3. After poll() returns, check each file descriptor's events parameter to determine the file descriptor's status.

Upvotes: 2

Related Questions