I'm trying to figure out how to use epoll() to poll a number of
sockets. Usually, I simply use poll or select to multiplex IO, but
I've read numerous times that epoll is faster, and more versatile.
However, I can't figure out how to use it, and the man page on epoll
is not very descriptive.

Firstly, all epoll examples I see assume a server/client model. I
want to use epoll to simply wait on a group of client sockets,
(connected to http servers) and fetch data from them. Is epoll()
capable of doing this?

Secondly, I don't understand the way the epoll functions are supposed
to work. The epoll_ctl function takes as arguments the epoll fd, the
client fd, and a pointer to an epoll_event struct. But the epoll
event struct also contains a file descriptor in it. It's unclear to
me what the purpose of epoll_event.fd is in relation to the client fd
passed to epoll_ctl.

Finally, how do you add multiple file descriptors? With poll() it's
simply a matter of creating an array of pollfd structs. With epoll
it's unclear how this is done. Do you make an array of epoll_event
structs? And if so, what is the relation between the file descriptors
contained in the epoll_event structs and the file descriptor passed to
epoll_ctl?

It's unclear to me whether you're supposed to pass an array of
epoll_event structures to epoll_ctl, or whether you're supposed to do
some kind of loop, adding file descriptors like:

for (int i = 0; i < NUM_FD; ++i) {
epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev);
}

Any explanation on how epoll is supposed to work would be appreciated
immensely.