Как реализовать тайм-аут epoll?

Я работаю над сетевым программированием с использованием epoll. Кажется, работает нормально. Я хотел бы добавить функцию тайм-аута, чтобы, если клиент не отправлял ничего в течение длительного периода времени, он просто отключил бы клиента.

Как мне это сделать? Я знаю, что могу установить время ожидания в epoll_wait, но это не для отдельного сокета...

Заранее спасибо...

3 ответа

Решение

Сохраните список сокетов, отсортированный по времени, оставшемуся до истечения времени ожидания (если период ожидания одинаков для всех сокетов, то это эквивалентно сортировке их по времени последнего полученного сообщения). Каждый раз, когда вы звоните epoll_wait()выберите розетку с наименьшим оставшимся временем до истечения времени ожидания (которое будет находиться в начале вашего списка). Используйте это время как тайм-аут в epoll_wait(),

когда epoll_wait() возвращает, после обработки любых активных сокетов, пройти через отсортированный список сокетов, удаляя все просроченные (которые будут в начале отсортированного списка).


В epoll_wait() время:

timeout = expirylist->expire_time - current_time();
n_events = epoll_wait(epfd, events, maxevents, timeout);

handle_events(events, n_events);

for (client = expirylist; client != NULL && client->expire_time < current_time(); client = client->expire_next)
{
    do_timeout(client);
}

Вы можете создать повторяющиеся timerfd и добавьте его в свой набор epoll. Он разбудит вас как угодно часто, и в этот момент вы сможете проверить все ваши клиентские соединения и отбросить те, которые вы считаете устаревшими.

Если ваш Linux слишком стар для поддержки timerfd, вы можете попробовать более старый timer_create,

Просто используйте libevent* или аналогичный; это сэкономит усилия на реализации ваших собственных очередей и проверке таймаутов. Это также может упростить вам использование epoll и, как дополнительное преимущество, будет более переносимым (скажем, вы хотите запустить свое приложение на FreeBSD, у которой нет epoll, но есть что-то концептуально похожее, называемое kqueue)

* другие похожие библиотеки доступны.

Другие вопросы по тегам