The kernel will fill in the events that occurred in the revents
field of your struct pollfd
array.
From the manual page:
The field revents is an output parameter, filled by the kernel with the events that actually occurred. The bits returned in revents can include any of those specified in events, or one of the values POLLERR, POLLHUP, or POLLNVAL. (These three bits are meaningless in the events field, and will be set in the revents field whenever the corresponding condition is true.)
If you want event notifications for accepted connections, then you need to either reserve space in advance or resize the struct pollfd
array for every connection.
You'll need some way to differentiate the listening socket. You could store it in index zero of your array.
int i, n;
n = poll(ufds, num_fds_in_array, timeout_value);
/* errors or timeout? */
if (n < 1)
;
for (i = 0; i < num_fds_in_array; i++) {
/* were there any events for this socket? */
if (!ufds[i].revents)
continue;
/* is it our listening socket? */
if (!i) {
if (ufds[0].revents & POLLIN)
/* call accept() and add the new socket to ufds */
else
/* error */
continue;
}
/* is there incoming data on the socket? */
if (ufds[i].revents & POLLIN)
/* call recv() on the socket and decide what to do from there */
}
The POLLOUT
flag is used to signal when the sending data on the socket will not block the caller.
For non-blocking I/O, I'd use a more powerful API since it requires more bookkeeping to do reliably. See the next paragraph.
Unfortunately, there's no room for auxiliary per-connection data to store state when using poll
. There are alternatives available depending on your platform, e. g. epoll for Linux, kqueue for *BSD, and a handful of options for Windows. If you want to use poll
with context data, you'd have to use a data structure that can be searched using the file descriptor or array index.