Я следую руководствам по kqueue (в частности, http://eradman.com/posts/kqueue-tcp.html и https://wiki.netbsd.org/tutorials/kqueue_tutorial/), и есть части, которые я не понимаю. Вот мой (отредактированный) код:
// 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
я не понимаю:
Правильно ли я установил nevents = BACKLOG, т.е. количество одновременных подключений? Если нет, то какими должны быть события?
Почему я проверяю
event_list[i].flags & EV_EOF
? Мое лучшее предположение: если соединение не удалось, пока сокет находился в очереди, я хочу удалить этот сокет из очереди? Но почему я снова звоню Кевенту?В том же разделе, что и предыдущий пункт, я вызываю
close(fd)
. Это правильно? В учебнике по эрадману есть дополнительное колдовство, но я не понимаю, почему.Если я правильно понимаю, kqueue может вернуться, когда я буду готов прочитать частичное сообщение. Как я узнаю, что сообщение готово?
Если это актуально, я работаю над OS X.