Synapse. TCP сервер. Отловить отключение клиента.

Модератор: Модераторы

Synapse. TCP сервер. Отловить отключение клиента.

Сообщение B4rr4cuda » 18.03.2012 03:04:38

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

Есть ТСПшный сервер, который при коннекте клиента, создает для него поток, который крутится и обрабатывает запросы клиента до тех пор, пока клиент не отключится. Идет взаимный обмен данными, но потом от клиента может не поступать инфы довольно продолжительное время. Отключаться нельзя, поэтому соединение остается активным.

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

Теперь вопрос, это нормальное поведение синапса или баг? Или я где-то накосячил?
Если нормальное, то есть ли более адекватные методы запроса состояния сокета, кроме регулярной отправки некоего пингового сообщения, чисто для определения состояния сокета? Подскажите, плз, т.к. лыжи уже не едут.

Все выглядит примерно так:

Код: Выделить всё
  while not Terminated do begin
        vRecvSockStr:='';

        //если есть инфа в буфере, то читаем
        if Sock.WaitingData>0 then begin
          vRecvSockStr := Sock.RecvPacket(2000);
          Self.AddLog('Сервер прочитал сообщение:'+vRecvSockStr);
        end;

        //Обработка ошибок сокета
        if Sock.LastError<>0 then begin
          AddLog(inttostr(Sock.LastError)+':'+sock.GetErrorDescEx);
          break;
        end;
       
        sleep(100);
        //!!!!!!!!!!!!!!!!!!!!!!!
        //дисконект заработает, если включить отсылку сообщения клиенту
        //Sock.SendString('ping');
     end;     
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение GrayEddy » 18.03.2012 03:57:16

Нормальное. Никакое соединение не может поддерживаться всю жизнь.

Сам сталкивался с такой проблемой.
На работе есть сервер. Написан на Delphi с применением TTCPServer + TTCPClient. Многопоточное приложение.
Следит за 43 контроллерами, данные передаются через модем GPRS который соединен с контроллером.
Контроллеры управляют уличным освещением. Поэтому - надежность и еще раз надежность.

Так вот, со стороны сервера юзером определяется количество попыток и интервал для проверки связи с клиентом.
В данном случае у меня 3 попытки, интервал через 5 минут. Если через 15 минут не получилось ни единой попытки соединиться с клиентом - сервер рвет связь с контроллером.
В контроллере идет непрерывно опрос на наличие связи с сервером. У меня 3 раза по 30 секунд (типа пинга). Если 3 попытки последовательно не удалось - контроллер сам рвет связь и пытается по новому соединиться с сервером.

PS: Если это Windows - смотрите в сторону неблокирующих соединений. На Королевстве Delphi есть прекрасные статьи Антона Григорьева насчет сокетов.
Библиотека Синапс использует только блокирующие соединения (по сути дела только одна нить).

На вашем месте я бы посмотрел LNet (если нужно кроссплатформенное решение) - ту используются неблокирующие соединения. + можно перехватить и обработать события связанные с установкой и разрывом связи.
Если только винда - ну что ж, Вин АПИ + асинхроннй режим + отдельный поток для ловли сообщений WSA_ (и на каждое новое соединение с клиентом - новый поток)

PPS: Пишу по памяти, все это реализовано года 3 назад.
Последний раз редактировалось GrayEddy 18.03.2012 04:14:51, всего редактировалось 1 раз.
GrayEddy
постоялец
 
Сообщения: 375
Зарегистрирован: 06.05.2005 09:37:56

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение Ism » 18.03.2012 04:12:29

Насколько я знаю TCP сокет обеспечивает только подтверждение передачи но не контроль состояния соединения.
Как вариант можно в случае долгого отсутствия приема информации пробовать проверить открыт ли порт клиента с которого идет инфа. Это буде чтото похожее на пинг но более оптимальное. То же можно сделать и со стороны клиента. В результате проверка будет производится только в случае долгого отсутствия инфы.

Вариант 2 , соединяться только для передачи приема и затем закрывать соединение. Это позволит быть уверенным, что хотябы на время обмена соединение работает.

Интересная ссылка http://rascal.su/blog/2010/09/11/zabbix-для-мониторинга-состояния-tcp-соединен/
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение GrayEddy » 18.03.2012 04:23:03

Ism писал(а):Насколько я знаю TCP сокет обеспечивает только подтверждение передачи но не контроль состояния соединения.


Не совсем так. Для Windows уже давно есть асинхронный режим , основанный на событияx WSA_, начиная с WinSock2. Как для Linux - без понятий.
Для первой версии WinSock - да, нет контроля.
GrayEddy
постоялец
 
Сообщения: 375
Зарегистрирован: 06.05.2005 09:37:56

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение EmeraldMan » 18.03.2012 12:33:43

В стандартном FCL, ssockets тоже очень просто отловить событие отключения. Это обычное сообщение от клиента, длина которого = 0.
На сколько я знаю, LNET основан как раз на FCL.
Мне очень нравится LNET, но столкнулся с тем, что надо было написать обработку каждого соединения отдельным потоком, с LNET были большие трудности, там как раз их очень удобная обвязка создает трудности для работы с потоками. Поэтому для совей задачи решил использовать стандартный FCL.
Аватара пользователя
EmeraldMan
постоялец
 
Сообщения: 149
Зарегистрирован: 16.10.2008 08:41:51
Откуда: Белгород

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение B4rr4cuda » 18.03.2012 13:39:35

GrayEddy,EmeraldMan,Ism Спасибо, вы мне очень помогли.

GrayEddy писал(а):Так вот, со стороны сервера юзером определяется количество попыток и интервал для проверки связи с клиентом. В данном случае у меня 3 попытки, интервал через 5 минут. Если через 15 минут не получилось ни единой попытки соединиться с клиентом - сервер рвет связь с контроллером.

Это хороший вариант.

GrayEddy писал(а):PS: Если это Windows - смотрите в сторону неблокирующих соединений. На Королевстве Delphi есть прекрасные статьи Антона Григорьева насчет сокетов.

У меня кроссплатформа, поэтому и решение нужно универсальное.

GrayEddy писал(а):На вашем месте я бы посмотрел LNet (если нужно кроссплатформенное решение) - ту используются неблокирующие соединения. + можно перехватить и обработать события связанные с установкой и разрывом связи.

Lnet у меня тоже используется но в клиентских частях. На сервере - Synapse.

EmeraldMan писал(а):В стандартном FCL, ssockets тоже очень просто отловить событие отключения. Это обычное сообщение от клиента, длина которого = 0.

Возможно стоит сделать серверную часть на FCLных сокетах. Надо подумать.

Ism писал(а):Вариант 2 , соединяться только для передачи приема и затем закрывать соединение. Это позволит быть уверенным, что хотябы на время обмена соединение работает.

Нельзя. Нужен постоянный коннект с клиентом. Если отваливается - определенные действия.
Аватара пользователя
B4rr4cuda
энтузиаст
 
Сообщения: 693
Зарегистрирован: 28.12.2007 07:48:35

Re: Synapse. TCP сервер. Отловить отключение клиента.

Сообщение ms301 » 08.10.2012 19:24:36

Может так:
отправляем клиенту к примеру 'HelloClient'.
Если клиент не ответил на эту строку(ну типа он должен отправить на сервер команду HelloServer)-то можно считать что клиент отлючился))
ms301
незнакомец
 
Сообщения: 1
Зарегистрирован: 08.10.2012 19:21:04


Вернуться в Сети

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru