Форум: "Сети";
Текущий архив: 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