На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Соблюдайте общие правила форума
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Указывайте точные версии Delphi и используемых сетевых библиотек.

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

Внимание:
попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Krid, user posted image Rouse_

Модераторы: Krid, Rouse_
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> Правила работы с соединениями в Indy 10 , Возможные варианты создания и закрытия соединений в Indy 10
    Спасибо, Oleg2004. Теперь кажется все ясно. Disconnect действительно просто инициировал процесс разъединения, но для его фактического убиения нужно было время. Если клиент пытался установить новое соединение до того, как старое убивалось, возникала ошибка Already connected. А использовать я это соединение повторно не мог, т.к. оно уже было "помечено" на удаление. Я правильно понял?
    Считаю, что предложенный medved_68 вариант работы клиента и объяснение Oleg2004 полностью описывают решение проблемы Already connected. Уже вторые сутки тестирую свое приложение по новой схеме - сбоев не обнаружено.
    Поскольку топик посвящен правилам работы с соединениями в Indy, то не хотелось бы ограничиться только Already connected. Если кто сталкивался еще с какими-то необычными ситуациями (подводными камнями) при организции сеансов связи в Indy, просьба поделиться :)

    To Felan: А ты как использовал CheckForGracefulDisconnect()? Он при нарушенном соединении генерит исключение EIdException. Достаточно отловить его и обработать так, как считаешь нужным. По крайней мере у меня так работает
    Сообщение отредактировано: VladDV -
      ExpandedWrap disabled
          try
            fIdClient.CheckForGracefulDisconnect( True );
         
            aCMD.RawAnswer.Clear;
            try
              fIdClient.SendCmd(aCMD.CMD, 200);
              aCMD.WirteBinary(fIdClient.Socket);
            finally
              GetAllLines(aCMD.RawAnswer);
            end;
          except
            on e: EidReplyRFCError do
              aCMD.RawAnswer.Add(e.Message);
            on e: EIdConnClosedGracefully do
              aCMD.RawAnswer.Add(e.Message);
          end;


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

      Еще вот это используется для установки доступности Action'ов
      ExpandedWrap disabled
        function TiaKiosk.isConnected: Boolean;
        begin
          fIdClient.CheckForGracefulDisconnect( False );
          Result := fIdClient.Connected;
        end;


      Ну и как я уже говорил в onDisconnect я делаю так

      ExpandedWrap disabled
            try
              GetAllLines(vRA);
            except
              on e: EIdConnClosedGracefully do
                DoOnDisconnected( vRA );
            end;


      Почему-то если не попытаться прочитать, то CheckForGracefulDisconnect не показывает адекватный результат. Даже если соединение уже закрыто, она говорит, что еще нет.
        Вот в чем прикол. Ты делаешь проверку CheckForGracefulDisconnect на клиенте, а я делал на сервере. На сервере вроде все работает. На клиенте я сейчас попробовал - действительно не работает. Причем пробовал два варианта:

        ExpandedWrap disabled
          Client.IOHandler.CheckForDisconnect(true, false);


        и

        ExpandedWrap disabled
          Client.CheckForGracefulDisconnect(True);


        Зато вполне хорошо работает такой вариант:
        ExpandedWrap disabled
          try
            if not Client.Connected then
              raise Exception.Create('Connection closed');
          except
            Exit;
          end;


        Почему не работает первый вариант - действительно загадка :)
          Давайте вернемся к нашим баранам :D
          Я не понимаю смысла проверки на клиенте с помощью спецфункции CheckForGracefulDisconnect() признака закрытия соединения со стороны сервера.
          В нормальных условиях таким признаком является возврат recv() нуля - именно сегмент FIN, полученный при нормальном завершении от сервера, заставляет recv() вернуть 0.
          Далее - есть такое суждение:
          Цитата
          CheckForDisconnect on the client. However for TCP to know the connection is
          down, it is often necessary to attempt to read/write to it.

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

            А как детектировать аварийный обрыв в переиод когда нет непосредственной передачи?
            Т.е. например, послали команду. Она прошла. Получили ответ... Пользователь отошел. Т.к. активности на сокете нет. Связь рвется (кто-то шнур выдернул). Пользователь приходит, смотрит - связь есть. А мне например надо, что бы если вдруг связь оборвалась программа это определили и когда пользователь вернулся, он сразу увидел, что связи нет, и для этого ему не надо было бы что-то делать?
              Цитата Felan @
              А мне например надо, что бы если вдруг связь оборвалась программа это определили

              Цитата Felan @
              (кто-то шнур выдернул).

              Felan если дело только за тем, что нет сети (сетевой кабель не подключен), то обрабатывай соответствующее сообщение Винды и прибивай сокеты. Или же делай по таймеру пробную запись байта в канал и анализируй результат. :) Разумеется сервер должен "знать" об этом байте или цепочке байт и игнорировать их при приеме или показывать пользователю, что соединение активно. Хотя это все придумано, режим Keep-Aliving если не ошибаюсь. :)
                Да это я знаю.
                Я так понял, что у Oleg2004 есть какое-то мега-знание... Хотел приобщиться. Может все это как-то более красиво реализовываться на Indy.
                  Цитата Felan @
                  что у Oleg2004 есть какое-то мега-знание...

                  :D
                  Да вовсе нет - просто я достаточно хорошо знаю протоколы и сетевое программирование - а вот INDY знаю только поверхостно
                  И если честно говорить, то только использование интерфейса сокетов дает полную свободу в сетевом программировании - компоненты этой свободы не имеют увы
                    Сейчас занимаюсь проектом, связанным с сетевым программированием (в частности, протокол TCP).
                    Столкнулся с подобной проблемой.

                    Объясню из-за чего она может возникать.
                    1. Сокет остался подключённым. Необходимо попробовать послать в него какие-либо данные и обработать исключение.
                    2. Остались данные во входящем буфере. Эта проблема часто возникает при неожиданном обрыве связи или тогда, когда ReadTimeout слишком мал (или же по техническим причинам клиент просто не дождался ответа. Этот вариант возникает чаще всего и именно он вводит программистов в ступор. Для решения проблемы необходимо очистить данный буфер после выполнения подключения, либо же до момента следующего подключения. Я пишу на С++, соответственно, это будет выглядеть так:
                    ExpandedWrap disabled
                      TCPClient->Disconnect(true);
                      if (!TCPClient->IOHandler->InputBufferIsEmpty()) {
                        TCPClient->IOHandler->InputBuffer->Clear();
                      }


                    Для Delphi, естественно:
                    ExpandedWrap disabled
                      TCPClient.Disconnect(true);
                      if not TCPClient.IOHandler.InputBufferIsEmpty then
                        TCPClient.IOHandler.InputBuffer.Clear;


                    Надеюсь, это поможет решить ваши проблемы :)
                    Сообщение отредактировано: arj99 -
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0355 ]   [ 17 queries used ]   [ Generated: 25.04.24, 03:56 GMT ]