Конференция "Сети" » Как правильно остановить IdTcpServer [D7, NT4, Win2k, WinXP]
 
  • Rav (30.10.07 13:16) [0]
    Создал связь на основе Indy TcpServer-TcpClient. Все нормально, связь устанавливается, клиент отправляет команды, сервер их обрабатывает. Когда закрываешь программу-клиент, не закрывая соединения, сервер "правильно" реагирует, показывая завершение соединения со стороны клиента. А наоборот не работает! То есть, если просто закрыть программу-сервер или физически разовать связь (например выдернуть кабель), клиент никак не отрегирует на произошедшее. Да и сервер спустя какое-то время ругается на ошибку потока (я так понимаю серверный или клиентский поток продолжают работать и после завершения работы основной программы).
    Собственно вопрос: как правильно закрыть клиентские соединения со стороны сервера перед его завершением, и если возможно, как отловить аварийное прерывание связи?
    С сетевыми компонентами практически не работал, буду признателен за любые подсказки, в т.ч. ссылки на статьи, литературу.
  • Сергей М. © (30.10.07 13:20) [1]
    Чем обоснован выбор именно Инди-компонентов ?
  • Rav (30.10.07 13:33) [2]

    > Чем обоснован выбор именно Инди-компонентов ?


    Во-первых, так до конца и не смог разобраться с TTcpServer/TTcpClient,... может кинете пару примеров работы с ними

    Во-вторых, в Indy есть встроенная обработка команд, то что мне нужно.
    Я только не понял, обработка команд идет в основном потоке, или в потоке клиента?
  • Сергей М. © (30.10.07 15:01) [3]

    > до конца и не смог разобраться с TTcpServer/TTcpClient


    Что тебе там конкретно непонятно ?

    И опять же - почему TTcpServer/TTcpClient ? Почему не TServerSocket/TClientSocket ? Почему не ICS-компоненты ?

    И разве на встроенной обработке команд свет клином сошелся ? Что мешает реализовать собственную ?


    > обработка команд идет в основном потоке, или в потоке клиента?


    В дополнительном.
  • umbra © (30.10.07 15:09) [4]

    > То есть, если просто закрыть программу-сервер или физически
    > разовать связь (например выдернуть кабель), клиент никак
    > не отрегирует на произошедшее.

    а откуда клиент может узнать, что кабель выдернули? Он узнает это только когда попытается послать серверу команду и не сможет.


    > Да и сервер спустя какое-то время ругается на ошибку потока

    А как именно ругается?
  • Сергей М. © (30.10.07 15:21) [5]

    > umbra ©   (30.10.07 15:09) [4]



    > как именно ругается?


    Вестимо как - превышение таймаута ожидания терминирования созданных сервером транспортных потоков.
  • Rav (30.10.07 21:54) [6]

    > Вестимо как - превышение таймаута ожидания терминирования
    > созданных сервером транспортных потоков.

    И как лечить?
  • Slym © (31.10.07 06:42) [7]
    Rav   (30.10.07 21:54) [6]
    И как лечить?

    Примерно так:
    try
     Sock.SendCmd
    except
     Sock.Close;
    end;

  • Сергей М. © (31.10.07 08:21) [8]

    > как лечить?


    Исправить логические ошибки в OnExecute
  • Rav (31.10.07 12:15) [9]

    > Исправить логические ошибки в OnExecute


    Я не использовал обработчик OnExecute - только встроенный процессор команд. Пока.
  • umbra © (31.10.07 14:20) [10]

    > > Вестимо как - превышение таймаута ожидания терминирования
    > > созданных сервером транспортных потоков.
    >
    > И как лечить?
    >


    сервер что, так и пишет "превышение таймаута ожидания терминирования ...."?
    Вы бы хоть класс исключения назвали.
  • Rav (01.11.07 12:30) [11]
    Если в 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
    то есть, потоки вроде бы должны быть остановлены и все сокеты закрыты, но этого почему-то не происходит.
  • Сергей М. © (01.11.07 12:34) [12]

    > потоки вроде бы должны быть остановлены


    С какого перепугу поток завершит выполнение, если он в момент команды терминирования занят блокирующим чтением/записью и, соответственно, не реагирует на команду ?
  • Rav (01.11.07 13:09) [13]
    И какже корректно прервать этот процесс?
    Хотя в этот момент чтение/запись как раз и не идет (по крайней меря я ничего через него не передаю)
  • Сергей М. © (01.11.07 13:39) [14]

    > в этот момент чтение/запись как раз и не идет


    А чем же тогда занят поток ?)
  • umbra © (01.11.07 13:41) [15]
    попробуйте увеличит значение свойства
    TerminateWaitTime

    сервера.
  • umbra © (01.11.07 13:44) [16]
    а лучше установите 10-й инди. Правда, тогда исходники придется править.
  • Rav (01.11.07 14:58) [17]

    > А чем же тогда занят поток ?)


    А хто его знаить? :-)
    Соединение "держит", но данные никакие не передаются.
    Согласен, если бы в этот момент что-то передавалось, но...

    Да ладно, Бог с ним, попробуем поковырять TTcpServer / TSocketServer
  • Сергей М. © (01.11.07 15:26) [18]

    > данные никакие не передаются


    Сервер при этом занят блокирующим чтением.
  • umbra © (01.11.07 16:05) [19]

    > Сервер при этом занят блокирующим чтением.
    >

    и что? это же не значит, что сокет, выделенный для клиента нельзя закрыть. А если поток не завершается, значит он занят еще чем-то или в нем возникло исключение, которое не обработано. Скорее всего - в обработчике команды.
 
Конференция "Сети" » Как правильно остановить IdTcpServer [D7, NT4, Win2k, WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0.001]