Понимание kqueue в TCP

Я следую учебники о 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

Я не понимаю

  1. Правильно ли я установить nevents = BACKLOG, то есть количество одновременных подключений? Если нет, то что должно быть?

  2. Почему я проверяю event_list[i].flags & EV_EOF? Мое лучшее предположение — если соединение не удалось, пока сокет находился в очереди, то я хочу удалить этот сокет из очереди? Но почему я снова называю kevent?

  3. В том же разделе, что и предыдущий пункт, я звоню close(fd), Это верно? У руководства eradman есть дополнительное колдовство, но я не понимаю почему.

  4. Если я правильно понимаю, kqueue может вернуться, когда я буду готов прочитать частичное сообщение. Как я знаю, когда сообщение завершено?

В случае, если это актуально, я работаю над OS X.

0

Решение

Быстрые мысли о коде / вопросах:

  1. Нет.

    Там нет требования, что BACKLOG == nevents,

    Вы можете выбирать события из очереди по одному или десятки за раз, в основном это касается ваших предпочтений и минимизации системных вызовов по сравнению с объемом памяти / стека.

    Также не очень часто все соединения будут запускаться одновременно … нет смысла тратить столько памяти, особенно если учесть большой параллелизм, это может означать, что большая память может привести к сбоям в кеше и, возможно, к снижению производительности.

  2. EV_EOF

    Фильтры могут установить этот флаг, чтобы указать специфичное для фильтра условие EOF

    Это означает, что вы должны указать фильтр, который может поднять этот флаг. Какие фильтры делают это? эти события вы слушаете?

    Вы можете найти их в man страница

    Один из примеров в сокетах — это когда клиент отключает read емкость, но оставляет write емкость розетки на месте. Чем EVFILT_WRITE Фильтр (если установлен) вызовет флаг EV_EOF.

    Лично я думаю, что эти крайние случаи можно проверить, когда write терпит неудачу вместо того, чтобы вызвать событие.

  3. призвание close разумно … действительно зависит от того, что вы хотите. Я мог бы сохранить соединение только для чтения данных. Или, может быть, вызвать shutdown, поскольку это считается более вежливым (но, вероятно, не так уж важно в наши дни).

  4. Вы не Это не проблема TCP / IP.

    Перенос сообщений должен выполняться реализуемым протоколом (т. Е. Websockets / HTTP). Каждый протокол имеет свой дизайн упаковки / завершения сообщения.

    Уровень TCP / IP упаковывает пакеты. В дикой природе они часто ограничены 1500 байтами, и многие части интернета занимают 576 байтов. Вы можете Google MTU для получения дополнительной информации.

Примечание:

  • Вы, вероятно, хотите добавить новых клиентов в kqueue,

  • Я хотел бы рассмотреть возможность сброса nchanges цени каждый цикл.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]