Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2007.04.01;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.038 c
2-1173238557
Expell
2007-03-07 06:35
2007.04.01
Перетащить картинку...


1-1170236837
SH@RK
2007-01-31 12:47
2007.04.01
Динамические массивы vs Статические массивы


2-1173162070
Ш-К
2007-03-06 09:21
2007.04.01
Анализ массива элементов


2-1173613570
НОВИЧЕК2007
2007-03-11 14:46
2007.04.01
Работа программы на другом компьютере.


3-1168333056
Андреевич
2007-01-09 11:57
2007.04.01
OLE DB error occured. Code 80040E2Fh - что означает?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский