Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.04.01;
Скачать: CL | DM;

Вниз

Отследить дисконнект клиентского сокета   Найти похожие ветки 

 
SpellCaster   (2006-10-18 17:00) [0]

Продолжаю доставать сообщество своими траблами с сокетами :).
Имеется две программы, общаются между собой через блокирующие TClient\ServerSocket.  Работа сервера выполняется в TServThread = class(TServerClientThread) (экземпляр потока получается при коннекте клиента в Server.OnGetThread), за обмен данными отвечает fSocketStream:=TWinSocketStream.Create(ClientSocket,3000).

Вопрос в следующем: как на сервере отследить, что клиент отсоединился? Хоть я и закрываю клиентский сокет при выходе из проги, сервер на это не реагирует. Я пробовал проверять всё, что только можно:
ClientSocket.Connected
ServerSocket.ActiveConnections
ServerSocket.ActiveThreads
ServerSocket.Connections[0].Connected
- и все эти св-ва исправно докладывают, что соединение есть!


 
medved_68 ©   (2006-10-19 10:19) [1]


> Вопрос в следующем: как на сервере отследить, что клиент
> отсоединился? Хоть я и закрываю клиентский сокет при выходе
> из проги, сервер на это не реагирует.

SpellCaster А что на сервере поток обслуживающий это клиентское соединение живет после его закрытия???? И если да то первый вопрос: "С какого перепугу?"  И если нет, то второй вопрос:
"А для чего придумано событие ServerSocketa OnThreadEnd???" :)))


 
Сергей М. ©   (2006-10-19 10:32) [2]


> все эти св-ва исправно докладывают, что соединение есть


В блок.режиме факт корректного разрыва соединения по инициативе партнера  может быть обнаружен только в ходе выполнения той или иной блокирующей ф-ции ввода/вывода (send/recv).


 
SpellCaster   (2006-10-19 10:58) [3]


> medved_68

В том-то и дело, что этот поток отлично себе циркулирует после закрытия клиента. События, естественно, никакого не происходит.


> Сергей М.

Мда, я так примерно и думал. Ну, с send понятно. А как насчет recv - ведь этот кусочек проходится нормально:


  len:=fSocketStream.Read(Buf^,MaxMsgLen);
  if len=0 then begin Sleep(300); Continue; end; // если ничего не получено


Возвращается 0, и цикл преспокойно катится дальше, хотя SocketStream по идее при ошибке чтения из сокета вызывает исключение. Как же определить, что соединение уже разорвано?
Попробовал вставить чистое чтение сокета, не через поток:

   clientsocket.ReceiveBuf(c,1);

Всё проходится на ура. Как быть? Не писать же тестовый байт в поток!
Пока что сделал так: при закрытии клиент посылает серверу команду дисконнекта, тот ее принимает и завершает поток. Вроде бы неплохо, но хочется выяснить, нельзя ли сделать проще.


 
medved_68 ©   (2006-10-19 11:09) [4]


> В том-то и дело, что этот поток отлично себе циркулирует
> после закрытия клиента. События, естественно, никакого не
> происходит.

SpellCaster у тебя  ошибка в программе потока, который не проверяет жизнеспособность клиента. В любом случае циркуляция потока и его работоспособность после разрыва очень ПОДОЗРИТЕЛЬНА. Так быть не должно. :)))


 
umbra ©   (2006-10-19 11:17) [5]

клиент может посылатю сообщение, что он отключается.


 
SpellCaster   (2006-10-19 11:20) [6]


> SpellCaster у тебя  ошибка в программе потока, который не
> проверяет жизнеспособность клиента.

Ну так в том-то и вопрос: КАК проверить жизнеспособность клиента!

> В любом случае циркуляция потока и его работоспособность
> после разрыва очень ПОДОЗРИТЕЛЬНА. Так быть не должно. :)))

Ну это уже претензии к Борману/Мелкософту ;)

> клиент может посылатю сообщение, что он отключается.

Согласен, я так и сделал. Но хочется убедиться, что более простых вариантов нет.


 
umbra ©   (2006-10-19 11:28) [7]

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


 
Сергей М. ©   (2006-10-19 11:29) [8]


> SocketStream по идее при ошибке чтения из сокета вызывает
> исключение


Все правильно.
Если искл-я нет, то партнер заведомо "жив".


 
medved_68 ©   (2006-10-19 11:58) [9]


> Ну это уже претензии к Борману/Мелкософту ;)

Да нет!!! Они то тут как раз и ни при чем! :))
> Согласен, я так и сделал. Но хочется убедиться, что более
> простых вариантов нет.

Еще один вариант - время жизни сокетного потока при отсутствии активности в сокете


 
Сергей М. ©   (2006-10-19 12:14) [10]


> medved_68 ©   (19.10.06 11:58) [9]


> время жизни сокетного потока при отсутствии активности в
> сокете


Вариант опять же сводится к определению факта "смерти" партнера.

Партнер же может "умереть" и не по своей воле (самое распространенная "смерть" - тётьнюра-уборщица со всей дури дернула шваброй за "жизнеобеспечивающий" провод компьютера)

Но при любой причине "смерти" гарантия ее своевременного обнаружения - своевременный вызов любой из транспортных ф-ций.


 
SpellCaster   (2006-10-19 12:34) [11]


> Сергей М.



> Все правильно.
> Если искл-я нет, то партнер заведомо "жив".


> Но при любой причине "смерти" гарантия ее своевременного
> обнаружения - своевременный вызов любой из транспортных
> ф-ций.

А clientsocket.ReceiveBuf(c,1); считается таковой? Если да, то никакой пользы от нее нет - она читает 0 байт и идёт дальше при закрытом приложении клиента.

Идея насчёт таймаута неплохая. Встрою её до кучи.


 
Сергей М. ©   (2006-10-19 12:51) [12]


> SpellCaster   (19.10.06 12:34) [11]



> clientsocket.ReceiveBuf(c,1); считается таковой? Если да,
>  то никакой пользы от нее нет - она читает 0 байт и ....


.. и это есть факт корректного закрытия соединения по инициативе партнера.


 
SpellCaster   (2006-10-19 13:53) [13]


> .. и это есть факт корректного закрытия соединения по инициативе партнера.

Да, но в том случае, если соединение ещё не завершено, она бесконечно ждёт появления в канале хоть какой-то инфы!


 
Сергей М. ©   (2006-10-19 14:08) [14]


> SpellCaster   (19.10.06 13:53) [13]


Не верно.

Блокирующий вызов ReceiveBuf(), вернувший 0, фиксирует факт корректного закрытия соединения по инициативе партнера.


 
medved_68 ©   (2006-10-19 14:59) [15]

SpellCaster А не проще ли использовать WaitForData??? тогда  если в течении какого то времени от клиента нет ответа и возврат из WaitForData <> WAIT_OBJECT_0 то принимается решение о смерти клиента и прибитии потока. Соответственно с выходом на событие ThreadEnd. :)))


 
SpellCaster   (2006-10-19 15:14) [16]


> Не верно.
> Блокирующий вызов ReceiveBuf(), вернувший 0, фиксирует факт
> корректного закрытия соединения по инициативе партнера.

У меня такое ощущение, что мы говорим на разных языках...

> Да, но в том случае, если соединение ещё не завершено, она
> бесконечно ждёт появления в канале хоть какой-то инфы!

Повторю по-другому: если запустить ReceiveBuf, когда соединение еще не закрыто, он повиснет до тех пор, пока в канал не поступит инфа. Так?


> А не проще ли использовать WaitForData??? тогда  если в
> течении какого то времени от клиента нет ответа и возврат
> из WaitForData <> WAIT_OBJECT_0 то принимается решение о
> смерти клиента и прибитии потока.

В принципе, да. Получится нечто вроде отслеживания времени неактивности канала, как в [9]. Наверно, так и сделаю.


 
SpellCaster   (2006-10-19 15:43) [17]

Хм, сделал с WaitForData


  len:=fSocketStream.Read(fBuf^,MaxMsgLen);
  if len=0 then // если ничего не получено - начинаем отсчитывать таймаут и усыпляем поток на некоторое время
  begin
   if not fSocketStream.WaitForData(10000) then Terminate else
   begin
    Sleep(300);
    clientsocket.ReceiveBuf(c,1);
    Continue;
   end;
  end;

Что в результате: обмениваемся данными, потом закрываем клиента - и WaitForData возвращает True! Заходим соответственно в цикл, читаем байт, ничего не получаем и на новую итерацию. И так без конца.
Пожалуй, всё-таки буду отслеживать время последнего обмена инфой.


 
Сергей М. ©   (2006-10-19 15:45) [18]


> SpellCaster   (19.10.06 15:14) [16]


> ощущение, что мы говорим на разных языках


Похоже на то.
Но истина - она одна)


> если запустить ReceiveBuf, когда соединение еще не закрыто,
>  он повиснет до тех пор, пока в канал не поступит инфа.
> Так?
>
>


Так.
Кр.того, она "отпустит" и в том случае, если "инфа в канал не поступила", но партнер в момент "виса" на блокирующем ReceiveBuf() закроет соединение по своей инициативе.


 
SpellCaster   (2006-10-19 16:53) [19]


> Кр.того, она "отпустит" и в том случае, если "инфа в канал
> не поступила", но партнер в момент "виса" на блокирующем
> ReceiveBuf() закроет соединение по своей инициативе.

А если не закроет по своей инициативе? Если вылетит, к примеру? Или уборщица провод выдернет ;)


 
Сергей М. ©   (2006-10-19 16:59) [20]


> SpellCaster   (19.10.06 16:53) [19]


И в этом случае она тоже обязана "отпустить".



Страницы: 1 вся ветка

Текущий архив: 2007.04.01;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.038 c
1-1171015510
DelphiLexx
2007-02-09 13:05
2007.04.01
FreeAndNil


1-1170698259
не забуду мать родную
2007-02-05 20:57
2007.04.01
GetClass


2-1173713275
FreeZ
2007-03-12 18:27
2007.04.01
Люди, нужна срочно Ваша помощь!


2-1173828969
Fantasy
2007-03-14 02:36
2007.04.01
Странно но факт. помогите понять


2-1173776010
Эшили
2007-03-13 11:53
2007.04.01
Самодельный Web-brouser