I am following tutorials about kqueue (specifically http://eradman.com/posts/kqueue-tcp.html and https://wiki.netbsd.org/tutorials/kqueue_tutorial/), and there are parts I don't understand. Here's my (edited) code:
// assume internal_socket is listening
void run_server(int internal_socket) {
const int nchanges = 1;
const int nevents = BACKLOG;
struct kevent change_list[nchanges];
struct kevent event_list[nevents];
int kq = kqueue();
if (kq == -1) {
// error
}
EV_SET(&change_list, sock_internal, EVFILT_READ, EV_ADD, 0, 0, 0);
while (true) {
int nev = kevent(kq, change_list, nchanges, event_list, nevents, NULL);
if (nev == -1) {
// error
}
for (int i = 0; i < nev; ++i) {
if (event_list[i].flags & EV_EOF) {
int fd = event_list[i].ident;
EV_SET(&change_list, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
if (kevent(kq, &change_list, nchanges, NULL, 0, NULL) == -1) {
// error
}
close(fd);
} else if (event_list[i].ident == sock_internal) {
int fd = accept(event_list[i].ident, ...);
// do stuff
} else if (event_list[i].flags == EVFILT_READ) {
int bytes_read = recv(event_list[i].ident, ...);
// do stuff
}
} // for
} // while (true)
} // func
I don't understand:
Am I right to set nevents = BACKLOG i.e. the number of concurrent connections? If not, what should nevents be?
Why do I check
event_list[i].flags & EV_EOF
? My best guess is if the connection failed while the socket was sitting in the queue, then I want to remove that socket from the queue? But why do I call kevent again?In the same section as the previous point, I call
close(fd)
. Is that correct? The eradman tutorial has some extra witchcraft but I don't understand why.If I understand correctly, kqueue could return when I am ready to read a partial message. How do I know when the message is complete?
In case it's relevant, I'm working on OS X.