2013-08-09 2 views
1

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

Я использую ОС freeBSD. Сервер работает с потоками Xamount (в зависимости от количества CPUcore). Поэтому я не разветвляюсь, и у каждого клиента нет собственного процесса.

Именно поэтому отправка deathpackage все time_t секунд, чтобы получить SIGPIPE, не является для меня вариантом. Но мне нужно удалить левые клиенты из kqueue, потому что иначе после слишком большого количества accept() мой код, очевидно, столкнется с проблемами памяти.

Есть ли способ, я могу проверить без высокой производительности на одного клиента, они связаны или нет?

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

ответ

0

Согласно kqueue man page, kevent() должен создать событие, когда розетка отключилась. Из описания го фильтра EVFILT_READ:

EVFILT_READ

принимает дескриптор в качестве идентификатора, и возвращается всякий раз, когда существует доступных для чтения данных. Поведение фильтра несколько отличается в зависимости от типа дескриптора.

Розетки

Sockets, которые ранее передавались слушать() возвращают, когда есть входящее соединение завершено. данные содержат размер отставания прослушивания.

Другие дескрипторы сокетов возвращаются, когда есть данные для чтения, с учетом значения SO_RCVLOWAT буфера сокета. Это может быть отменено с помощью метки с низким уровнем воды для фильтра в момент добавления фильтра, установив флаг NOTE_LOWAT в fflags и указав новый знак низкой воды в данных. При возврате данные содержат количество байтов данных протокола, доступных для чтения.

Если направление считывания сокета завершено, фильтр также устанавливает EV_EOF в флаги и возвращает ошибку сокета (если есть) в fflags. Возможно, что EOF будет возвращен (показывая, что соединение исчезло), в то время как в буфере сокета есть еще данные.

1

Редактировать: этот ответ пропускает вопрос, потому что речь идет не об использовании kqueue. Но если кто-то находит вопрос по названию, это может быть полезно в любом случае ...

Я часто видел следующее поведение: если клиент умирает, а сервер делает select() на дескриптор сокета клиента, select() возвращается с кодом возврата> 0 и FD_ISSET(fd) будет верным для этого дескриптора. Но когда вы теперь пытаетесь прочитать форму сокета, read() (или recv()) верните ERROR.

Для «нормального» соединения, использующего это для обнаружения смерти клиента, отлично подходит для нас, но, похоже, другое поведение, когда соединение сокетов туннелировано, но нам пока не удалось полностью понять это.

+0

да, но дело в том, Kqueue имеет поведение замены выберите(), так что им не с помощью выбора в любом случае;) – dhein

+0

нормально извините, и дайте угадаю, 'KEVENT()' не ведет например 'select()' в этом случае? –

+0

yip, kevent() - это своего рода eventlistener, который возвращает мне список всех сокетов, которые запускают специальное событие, то есть что-то готово для записи или чтения. поэтому, если есть сокет, который закрыт клиентом, kevent() просто больше не будет передавать какие-либо события этого сокета. То почему я думаю, обработка таймера для каждого сокета была бы способом с большой свободной производительностью. (Поскольку у меня было для каждого сокета, чтобы увеличить собственное значение времени, то, что абсолютное пропустило бы поведение kqueue(), на мой взгляд) – dhein

Смежные вопросы