URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 4408
[ Назад ]

Исходное сообщение
"как отследит состояние сокета"

Отправлено Savva , 27-Июн-05 16:59 
нельзя ли как нить узнать открыт ли сокет (т.е. установлено ли соединение) с клиентом со стороны сервера ?

Но так что бы не посылать что нибудь в сокет и смотреть код ошибки.

использую gcc, пишу под линукс


Содержание

Сообщения в этом обсуждении
"как отследит состояние сокета"
Отправлено Alexander S. Salieff , 27-Июн-05 18:30 
>нельзя ли как нить узнать открыт ли сокет (т.е. установлено ли соединение)
>с клиентом со стороны сервера ?
>
>Но так что бы не посылать что нибудь в сокет и смотреть
>код ошибки.
>
>использую gcc, пишу под линукс

Перебираем весь пул сокетов, делаем им getpeername/getsockname. Тока если есть пул, и он постоянно в обработке (poll/select) то и так должно быть ясно, кто подконнекчен и жив ли он. ИМХО, есть смысл задуматься над архитектурой ПО


"как отследит состояние сокета"
Отправлено Savva , 28-Июн-05 09:43 
>Перебираем весь пул сокетов, делаем им getpeername/getsockname. Тока если есть пул, и
>он постоянно в обработке (poll/select) то и так должно быть ясно,
>кто подконнекчен и жив ли он. ИМХО, есть смысл задуматься над
>архитектурой ПО

Я для каждого клиента создаю тред и там его обрабатываю (жду данных от клиента select+recv) при получении данных соответствующе отвечаю (send). Важно что б с одним клиентом было одно соединение и если вдруг оборвалась связь с клиентом (аппаратно, например обрыв кабеля) я должен об этом узнать и закрыть сокет, ожидая клиента вновь. Клиент может посылать данные очень редко, но на связи должен быть всегда. Пинговать его жуть как неохота, вот и хотелось бы отслеживать состояние сокета без записи/чтения данных в этот сокет (есть сокет == есть соединение с клиентом).

Так если создать массивчик дескрипторов открытых сокетов и юзать getpeername/getsockname должно все получиться?


"как отследит состояние сокета"
Отправлено DEC , 28-Июн-05 11:19 
>хотелось бы отслеживать состояние сокета без записи/чтения
>данных в этот сокет (есть сокет == есть соединение с клиентом).

А, интересно, почему Вам так не хочется записывать в сокет? Ну вернёт он EPIPE, ну обработаете Вы его. Чего сташного, я не понимаю.
А для постоянного отслеживания состояния клиента есть SO_KEEPALIVE, который генерит тот-же SIGPIPE.  Да ещё есть SO_RCVTIMEO.



"как отследит состояние сокета"
Отправлено Alexander S. Salieff , 28-Июн-05 14:26 
>>Перебираем весь пул сокетов, делаем им getpeername/getsockname. Тока если есть пул, и
>>он постоянно в обработке (poll/select) то и так должно быть ясно,
>>кто подконнекчен и жив ли он. ИМХО, есть смысл задуматься над
>>архитектурой ПО
>
>Я для каждого клиента создаю тред и там его обрабатываю (жду данных
>от клиента select+recv) при получении данных соответствующе отвечаю (send). Важно что
>б с одним клиентом было одно соединение и если вдруг оборвалась
>связь с клиентом (аппаратно, например обрыв кабеля) я должен об этом
>узнать и закрыть сокет, ожидая клиента вновь. Клиент может посылать данные
>очень редко, но на связи должен быть всегда. Пинговать его жуть
>как неохота, вот и хотелось бы отслеживать состояние сокета без записи/чтения
>данных в этот сокет (есть сокет == есть соединение с клиентом).
>
>
>Так если создать массивчик дескрипторов открытых сокетов и юзать getpeername/getsockname должно все
>получиться?

Нет, это не совсем так.
Во первых, сразу несколько полезных замечаний, по личному опыту проектирования пром-серверов. Лучше юзать poll вместо select. Непонятно, зачем вам создавать тред+демультиплексор для каждого клиента? Почему не загнать все сокеты в один демультиплексор, и надежнее и гемору с тредами, блокировками, синхрами, etc меньше.
Теперь к вопросу о доступности клиента. Пинговать его явно необязательно, ICMP составляющая и так отрабатывает в tcp-стеке, и если он порастет по тем или иным причинам, то на сокете поднимется флаг ошибки, а вы его сможете получить, через except-set в select'е или POLLERR/POLLHUP-event в poll'е. Правда стандартное время реакции ядра базового дистра на это событие около 3х минут, что нервирует, но эта трабла решается с помощью setsockopt.


"как отследит состояние сокета"
Отправлено Savva , 28-Июн-05 15:03 
поясню ситуацию: есть кучка удаленных аппаратов в которых вроли сигнализации используется GPRS-модем. Требуется всегда знать что аппарат на месте и оперативно узнать если сработал какой либо из датчиков.

Если сокет открыт (а именно установлен канал связи), значит аппарат наместе. Т.к. установлен ли канал связи нельзя проверить (?) ничего не послав в него приходится аппараты постоянно "пинговать" (имел ввиду не ping 1.2.3.4, а переодическую отправку данных в сокет и смотреть результат)

>Непонятно, зачем вам создавать тред+демультиплексор для каждого
>клиента?
select здесь использовал как удобное средство для одновременного обратного отсчета (т.е. аппарат не подовал признаков жизни t секунд значит пора бить тревогу) и собственно ожидания не придет ли что с аппарата.
а тред использовал из-за опасений вдруг что пойдет не так и как бы прога не заблокировалась при обработке одного клиента... тут ядро само разрулит и даст право на жизнь другим клиентам


>Почему не загнать все сокеты в один демультиплексор, и надежнее
>и гемору с тредами, блокировками, синхрами, etc меньше.
возможно все так и придется сделать


>Теперь к вопросу о доступности клиента. Пинговать его явно необязательно, ICMP составляющая
>и так отрабатывает в tcp-стеке, и если он порастет по тем
>или иным причинам, то на сокете поднимется флаг ошибки, а вы
>его сможете получить, через except-set в select'е или POLLERR/POLLHUP-event в poll'е.
но для этого все равно придется чтонибудь в сокет заслать как я понимаю? не ждать же SO_KEEPALIVE...


"как отследит состояние сокета"
Отправлено Alexander S. Salieff , 28-Июн-05 15:21 
>>Теперь к вопросу о доступности клиента. Пинговать его явно необязательно, ICMP составляющая
>>и так отрабатывает в tcp-стеке, и если он порастет по тем
>>или иным причинам, то на сокете поднимется флаг ошибки, а вы
>>его сможете получить, через except-set в select'е или POLLERR/POLLHUP-event в poll'е.
>но для этого все равно придется чтонибудь в сокет заслать как я
>понимаю? не ждать же SO_KEEPALIVE...

Отчего же не ждать? Выставить его в нужное значение посредством setsockopt и ждать.


"как отследит состояние сокета"
Отправлено Savva , 28-Июн-05 17:40 
>>не ждать же SO_KEEPALIVE...

>Отчего же не ждать? Выставить его в нужное значение посредством setsockopt и
>ждать.

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


"как отследит состояние сокета"
Отправлено DEC , 28-Июн-05 19:11 
>Быть может книжка то не умная, а "умная"? Как оно в реальной
>жизни под линуксом? и если есть возможность, то с примерчиком.
Книжка умная, но не очень свежая, наверное :-)

поищи на тему TCP_KEEPIDLE и TCP_KEEPINTVL, примеров, извини, не приведу.


"как отследит состояние сокета"
Отправлено BorisPolevoy , 20-Июл-05 17:25 
>поясню ситуацию: есть кучка удаленных аппаратов в которых вроли сигнализации используется GPRS-модем.
>Требуется всегда знать что аппарат на месте и оперативно узнать если
>сработал какой либо из датчиков.
>
>Если сокет открыт (а именно установлен канал связи), значит аппарат наместе. Т.к.
Сокет - это файловый дескриптор, который ничего не знает о соединении. Сама структура стека TCP/IP не позволяет оперативно узнать об обрыве связи (отключении клиента). Это позволяют только сети с установлением соединения, например, X.25.

>установлен ли канал связи нельзя проверить (?) ничего не послав в
>него приходится аппараты постоянно "пинговать" (имел ввиду не ping 1.2.3.4, а
>переодическую отправку данных в сокет и смотреть результат)
>
Проще в данном случае использовать UDP, по которому каждый аппарат будет с заданной переодичностью (зависит от скорости канала и количества аппаратов) передавать свой уникальный номер и какую-либо временную отметку (простой счетчик).
Сервер на один открытый сокет принимает UDP пакеты от всех аппаратов и по их идентификаторам судит об их состоянии.
Как аппараты будут узнавать адрес/порт сервера зависит от протокола, примеры см. в SIP/RTP и прочих H.323.


"как отследит состояние сокета"
Отправлено Алексей Соколов , 24-Апр-06 04:15 
>>Если сокет открыт (а именно установлен канал связи), значит аппарат наместе. Т.к.
>Сокет - это файловый дескриптор, который ничего не знает о соединении. Сама
>структура стека TCP/IP не позволяет оперативно узнать об обрыве связи (отключении
>клиента). Это позволяют только сети с установлением соединения, например, X.25.

А как же, позвольте, TCP/IP это протокол без установления соединения?