-
Создал связь на основе Indy TcpServer-TcpClient. Все нормально, связь устанавливается, клиент отправляет команды, сервер их обрабатывает. Когда закрываешь программу-клиент, не закрывая соединения, сервер "правильно" реагирует, показывая завершение соединения со стороны клиента. А наоборот не работает! То есть, если просто закрыть программу-сервер или физически разовать связь (например выдернуть кабель), клиент никак не отрегирует на произошедшее. Да и сервер спустя какое-то время ругается на ошибку потока (я так понимаю серверный или клиентский поток продолжают работать и после завершения работы основной программы).
Собственно вопрос: как правильно закрыть клиентские соединения со стороны сервера перед его завершением, и если возможно, как отловить аварийное прерывание связи?
С сетевыми компонентами практически не работал, буду признателен за любые подсказки, в т.ч. ссылки на статьи, литературу.
-
Чем обоснован выбор именно Инди-компонентов ?
-
> Чем обоснован выбор именно Инди-компонентов ?
Во-первых, так до конца и не смог разобраться с TTcpServer/TTcpClient,... может кинете пару примеров работы с ними
Во-вторых, в Indy есть встроенная обработка команд, то что мне нужно.
Я только не понял, обработка команд идет в основном потоке, или в потоке клиента?
-
> до конца и не смог разобраться с TTcpServer/TTcpClient
Что тебе там конкретно непонятно ?
И опять же - почему TTcpServer/TTcpClient ? Почему не TServerSocket/TClientSocket ? Почему не ICS-компоненты ?
И разве на встроенной обработке команд свет клином сошелся ? Что мешает реализовать собственную ?
> обработка команд идет в основном потоке, или в потоке клиента?
В дополнительном.
-
> То есть, если просто закрыть программу-сервер или физически
> разовать связь (например выдернуть кабель), клиент никак
> не отрегирует на произошедшее.
а откуда клиент может узнать, что кабель выдернули? Он узнает это только когда попытается послать серверу команду и не сможет.
> Да и сервер спустя какое-то время ругается на ошибку потока
А как именно ругается?
-
> umbra © (30.10.07 15:09) [4]
> как именно ругается?
Вестимо как - превышение таймаута ожидания терминирования созданных сервером транспортных потоков.
-
> Вестимо как - превышение таймаута ожидания терминирования
> созданных сервером транспортных потоков.
И как лечить?
-
Rav (30.10.07 21:54) [6]
И как лечить?Примерно так:
try
Sock.SendCmd
except
Sock.Close;
end;
-
> как лечить?
Исправить логические ошибки в OnExecute
-
> Исправить логические ошибки в OnExecute
Я не использовал обработчик OnExecute - только встроенный процессор команд. Пока.
-
> > Вестимо как - превышение таймаута ожидания терминирования
> > созданных сервером транспортных потоков.
>
> И как лечить?
>
сервер что, так и пишет "превышение таймаута ожидания терминирования ...."?
Вы бы хоть класс исключения назвали.
-
Если в OnClose формы НЕ ОСТАНАВЛИВАТЬ сервер (IdTcpServer.Active := False)
то ошибка следующая: "Exception EIdTerminateThreadTimeout in module.... Terminate Thread Timeout",
если в OnClose формы ОСТАНАНОВИТЬ сервер (IdTcpServer.Active := False)
то форма "зависает" и через какое-то время выдает ту же ошибку "Terminate Thread Timeout", но уже "штатно" не закрывается
Я покопался в исходниках с надыбал следующий код при остановке сервера
TerminateListenerThreads;
// Tear down ThreadMgr
try
TerminateAllThreads;
finally
if ImplicitThreadMgr and TIdThreadSafeList(Threads).IsCountLessThan(1) then begin // DONE -oAPR: BUG! Threads still live, Mgr dead ;-(
FreeAndNil(FThreadMgr);
FImplicitThreadMgr := False;
end;
end;//tryf
то есть, потоки вроде бы должны быть остановлены и все сокеты закрыты, но этого почему-то не происходит.
-
> потоки вроде бы должны быть остановлены
С какого перепугу поток завершит выполнение, если он в момент команды терминирования занят блокирующим чтением/записью и, соответственно, не реагирует на команду ?
-
И какже корректно прервать этот процесс?
Хотя в этот момент чтение/запись как раз и не идет (по крайней меря я ничего через него не передаю)
-
> в этот момент чтение/запись как раз и не идет
А чем же тогда занят поток ?)
-
попробуйте увеличит значение свойства
TerminateWaitTime
сервера.
-
а лучше установите 10-й инди. Правда, тогда исходники придется править.
-
> А чем же тогда занят поток ?)
А хто его знаить? :-)
Соединение "держит", но данные никакие не передаются.
Согласен, если бы в этот момент что-то передавалось, но...
Да ладно, Бог с ним, попробуем поковырять TTcpServer / TSocketServer
-
> данные никакие не передаются
Сервер при этом занят блокирующим чтением.
-
> Сервер при этом занят блокирующим чтением.
>
и что? это же не значит, что сокет, выделенный для клиента нельзя закрыть. А если поток не завершается, значит он занят еще чем-то или в нем возникло исключение, которое не обработано. Скорее всего - в обработчике команды.