Обнаружение незанятого соединения в неблокирующем сокете

Я пишу TCP-сервер, который использует неблокирующие сокеты и epoll () для мультиплексирования ввода-вывода. Я хочу обнаружить незанятые соединения, чтобы их закрыть. Я не могу использовать setsockopt с RCVTIMEO, потому что сокеты не блокируются. Как мы можем установить тайм-аут для неблокирующего сокета? Это связано с другим моим вопросом: Тайм-аут простаивающих соединений на сервере на базе epoll Если добубл пост, скажите, и я удалю тот или иной вопрос.

0
0
455
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Используйте таймер с розеткой. Библиотека цикла событий, которую вы используете, должна предоставлять таймеры.

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

Я делаю это, я сохраняю переменную last_active time_t, связанную с каждым подключением, которую я обновляю до текущего времени в обработчике событий. Перед тем как это сделать, я проверяю, не прошло ли больше разрешенного времени с момента последнего события, и если да, я прерываю соединение. Это не совсем то, что я хочу, потому что тайм-аут срабатывает только при первом несвоевременном событии, но если соединение остается неактивным, мой код не обнаруживает его, пока оно снова не станет «активным». Я использую epoll напрямую, я не использую никакую библиотеку событий.

Mihai 10.08.2018 16:41

@miguel Это не тот таймер, который вы описали. Используемые вами таймеры должны вызывать ваш обратный вызов по истечении срока его действия.

Maxim Egorushkin 10.08.2018 16:46

Ммм ... спасибо. Есть идеи, как это сделать без библиотеки событий, такой как libevent?

Mihai 10.08.2018 16:51

@miguel Используйте аргумент тайм-аута для epoll. Отслеживайте текущее время. По прошествии достаточного времени выполните обнаружение мертвых клиентов. Я собирался предложить использовать libevent.

Maxim Egorushkin 10.08.2018 16:53

Спасибо, я сделаю это. Вместо линейного обхода набора соединений я собираюсь использовать очередь с приоритетом для тайм-аута, когда следующее соединение должно быть отключено, как описано здесь stackoverflow.com/questions/8544856/….

Mihai 10.08.2018 17:07

Вам не нужна очередь с приоритетом, если все значения тайм-аута одинаковы. Новые тайм-ауты всегда будут помещаться в начало очереди, а те, у которых есть ближайшее время тайм-аута, всегда будет в конце.

Martin James 10.08.2018 18:17

@miguel С libevent этого делать не нужно. Просто зарегистрируйте событие чтения для вашего сокета fd вместе с таймером. Libevent внутренне поддерживает таймеры в минимальной куче (мой вклад в libevent в 2006 году) и использует самое раннее истечение таймера в качестве тайм-аута для epoll.

Maxim Egorushkin 10.08.2018 23:32

@MaximEgorushkin спасибо, но я пытаюсь написать минимальную программу без зависимостей, в будущем проекте я обязательно буду использовать libevent.

Mihai 12.08.2018 09:00

да, но что произойдет, когда соединение, которое должно было быть в начале очереди, разорвется? Теперь вам нужно знать, какое следующее соединение запланировано на тайм-аут. Это тот, у которого самая низкая последняя активная временная метка. Чтобы знать, что нам нужна приоритетная очередь и обновлять позицию соединения, когда в нем происходит событие

Mihai 12.08.2018 09:21

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