Перейти к содержанию
  • 0
Wovan2

IdTCPClient-IdTCPServer управление соединением

Вопросы

Доброе время суток.

Борюсь с Indy 10 на FMX. Обмен данными между сервером и клиентом наладил. Все работает стабильно.

Стал экспериментировать с разрывом связи. И тут программы ведут себя не очень понятно, особенно на клиенте. Если сервер не запушен. Клиент на команде IdTCPClient.Connect; закрывается. ???? Делаю обработки так
 

procedure TfrmMainClient.TimerTimer(Sender: TObject);
var
 Server : string;
begin
 if not IdTCPClient.Connected
  then
   try
    IdTCPClient.Connect;
   except
   on E : Exception do
    lblInfo.Text := e.Message;
   end;
 Server := 'Сервер ' + IdTCPClient.Socket.Binding.PeerIP +
           ':' + IntToStr(IdTCPClient.Socket.Binding.PeerPort);
 if IdTCPClient.Connected
  then
   begin
    lblInfo.Text := Server + ' подключен!';
    lblInfo.TextSettings.FontColor := TAlphaColors.Green;
   end
  else
   begin
    lblInfo.Text := Server + ' не доступен!';
    lblInfo.TextSettings.FontColor := TAlphaColors.Red;
   end;
end;

Никаких сообщений не появляется. Программа подвисает вместе с Адроидом, потом тупо окно закрывается. Молча. Таймауты на клиенте выставил ConnectTimeOut = 5000; ReadTimeOut = 5000;
В общем вопрос. Как правильно организовать на Indy управление соединением? Чтобы не тормозило, Была возможность переподключиться. 

PS. Почему-то в Delphi 10.2 не могу найти компонент AntiFreeze. ????

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендуемые сообщения

  • 0

Не знаю глюк это или что, но в приложении я этот объект даже не могу в run-time увидеть:huh:

Еще здесь на форуме упоминается какой-то ProgressDialog, но я у себя не могу его найти.

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
4 часа назад, Wovan2 сказал:

Не знаю глюк это или что, но в приложении я этот объект даже не могу в run-time увидеть:huh:

Делал Enabled := true энииндикатору?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Перед долгим кодом делал

 r1.Visible:= true; //TRectangle
 r1.BringToFront;
 ai1.Enabled := true;

В конце

  ai1.Enabled := false;
  r1.Visible:= false;

В результате вообще ничего не видно. 

Ну почему все так не очевидно и не понятно. Неужели какой-нибудь стандартной анимашки нет??? Пробовал и через BitmapListAnimation1.Enabled := true; Результат примерно такой же отображается первый кадр и все. Может через поток надо как-то это делать??? Блин по полдня надо тратить на тривиальные вещи

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
2 минуты назад, Wovan2 сказал:

Пробовал и через BitmapListAnimation1.Enabled := true; Результат примерно такой же отображается первый кадр и все. Может через поток надо как-то это делать??? Блин по полдня надо тратить на тривиальные вещи

Значит вы блокируете основной поток, поэтому не видите изменений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Да. Похоже на это. Ну нафиг эти красивости

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
5 часов назад, Wovan2 сказал:

Перед долгим кодом делал

http://fire-monkey.ru/forum/183-tfgactivitydialog/

Вот этот компонент спасет отца русской демократии.

Правда, для винды его пришлось чуть дополнить (на самом деле Ярослав уже всё сделал, я только мелкие шероховатости поправил).

Отредактировал kami

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
4 часа назад, Wovan2 сказал:

Да. Похоже на это. Ну нафиг эти красивости

Я все-таки повторю свой вопрос: если в одной из реализаций ты пришел к взаимодействию вида запрос-ответ-разрыв связи, то почему не использовать http вместо tcp?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
11 час назад, POV сказал:

Всё же ты придёшь к потоку ))

Для меня потоки не новость. Работать с ними приходилось. Но в данном случае это как-то усложняет все дело.

10 часов назад, kami сказал:

Я все-таки повторю свой вопрос: если в одной из реализаций ты пришел к взаимодействию вида запрос-ответ-разрыв связи, то почему не использовать http вместо tcp?

Еще потерять кучу времени, чтобы понять как работают новые компоненты?

На данный момент я убрал или сделал проверки на существование внутренних объектов IdTCPClient и IdTCPServer, где они проскакивали в коде - вываливания и на сервере и на клиенте прекратились. Подключение проверяю при каждом обращении к серверу, при отсутствии происходит переподключение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
Только что, Wovan2 сказал:

Еще потерять кучу времени, чтобы понять как работают новые компоненты?

Зато избавиться от проблем, которые еще не обнаружились, 100% не проявятся при соединении внутри одного компьютера, в 95% случаев не проявятся в одноранговой локалке... но принесут дикую головную боль в этих оставшихся 5%,  и 100% будут при соединении через интернет.
В отличие от http, в котором все такие проблемы уже решены и реализована именно нужная тебе схема: отправил запрос и получил ответ.
Но - хозяин-барин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Вот, если поможет. Стабильно работающий в одном из проектов код. Для получения строки с сервера используется FIdTCPClient.IOHandler.ReadLnWait - там уже есть все что нужно, что бы получить строку с сервера в течении FIdTCPClient.ReadTimeout:=constReadTimeout (милисекунды).

 

procedure TTCPThread.CreateNetwork;
begin
  FIdTCPClient:=TIdTCPClient.Create(Nil);
  FIdTCPClient.Host:=FInstance.Host;
  FIdTCPClient.Port:=FInstance.Port;
  FIdTCPClient.ConnectTimeout:=constConnectTimeout; //100ms
  FIdTCPClient.ReadTimeout:=constReadTimeout; //100ms
end;

procedure TTCPThread.SendCommand(const ACommand : TCommand; var AThreadResult : TThreadResult);
begin
  if Not FIdTCPClient.Connected then
    try
      FIdTCPClient.Connect;
    except
      on E:Exception do
      begin
        AThreadResult.Error:=True;
        AThreadResult.ErrorMessage:=E.Message;
        exit;
      end;
    end;
  if FIdTCPClient.Connected then
  begin
    try
      FIdTCPClient.Socket.WriteLn(ACommand.CommandString);
    except
      on E:Exception do
      begin
        AThreadResult.Error:=True;
        AThreadResult.ErrorMessage:=E.Message;
        exit;
      end;
    end;
    try
      AThreadResult.JSONString:=FIdTCPClient.IOHandler.ReadLnWait;
    except
      on E:Exception do
      begin
        AThreadResult.Error:=True;
        AThreadResult.ErrorMessage:=E.Message;
        exit;
      end;
    end;
    AThreadResult.JSONString:=AThreadResult.JSONString.Trim;
  end
  else
  begin
    AThreadResult.Error:=True;
    AThreadResult.ErrorMessage:='Not connected';
  end;
end;

Синхронизация с основным потоком:

procedure TTCPThread.Execute;
Var ACommand : TCommand;
    AThreadResult : TThreadResult;
begin
  while Not Terminated do
    if FQueueRequest.PopItem(ACommand) = TWaitResult.wrSignaled Then
    begin
      AThreadResult.Error:=False;
      AThreadResult.ErrorMessage:='';
      AThreadResult.Process:=ACommand.Process;
      AThreadResult.Command:=ACommand.Command;
      AThreadResult.CommandName:=ACommand.CommandName;
      AThreadResult.JSONString:='';
      SendCommand(ACommand, AThreadResult);
      if Assigned(FOnReceiveData) then
        TThread.Synchronize(Self,
          procedure
          begin
            FOnReceiveData(Self, AThreadResult);
          end);
      if AThreadResult.Error then
        while FQueueRequest.PopItem(ACommand) = TWaitResult.wrSignaled do
        begin
        end;
    end;
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Как различать клиентов между собой? При каждом пакете клиенту сообщать свой уникальный номер?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

@Wovan2, после подключения клиента к серверу, занимаемая сервером память подскакивает до 1Гб :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
12 минуты назад, Rusland сказал:

@Wovan2, после подключения клиента к серверу, занимаемая сервером память подскакивает до 1Гб :)

Ну это вопрос к Indy. Моего кода в приложении очень мало.

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

Знаете. Сейчас посмотрел. Сервер запущен на Win10. Без подключений 8.2 Мб. Один клиент 8.3 Мб. Два клиента - тоже 8.3 Мб.

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, Rusland сказал:

Как различать клиентов между собой? При каждом пакете клиенту сообщать свой уникальный номер?

На сервере проблем в этом нет. Событие procedure IdTCPServerExecute(AContext: TIdContext) в параметре принимает контекст соединения. Там вся информация о соединении инициировавшем это событие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
1 час назад, Rusland сказал:

При обрыве соединения и переподсоединении будет новый контекст :)

Разумеется и новый ответ. А первое соединение должно закрыться по ошибке. Видимо.

Отредактировал Wovan2

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Похожий контент

    • От Sashar333
      Здравствуйте!.Delphi 10.2. Android 6 (Xiaomi Redmi note 4)
      программирую раз в год, уровень языка минимальный, наверно.
      код:
      procedure TForm1.FormCreate(Sender: TObject);
      begin
      {$IFDEF MSWINDOWS}
      pflog:='log.bas';
      pfmem:='mem.mem';
      pfprod:='prod.txt';
      pfpost:='post.txt';
      {$ELSE} {$IFDEF IOS}
      //код для мобильной платформы iOS
      {$ELSE} {$IFDEF ANDROID}
      pflog:=Tpath.GetDocumentsPath+pathdelim+'log.bas';
      pfmem:=Tpath.GetDocumentsPath+pathdelim+'mem.mem';
      pfprod:=Tpath.GetDocumentsPath+pathdelim+'prod.txt';
      pfpost:=Tpath.GetDocumentsPath+pathdelim+'post.txt';
      {$ENDIF}
      {$ENDIF}
      {$ENDIF}
      memo1.Text:='';
      if not(fileexists(pfmem)) then memo1.Lines.SaveToFile(pfmem);
      memo1.Lines.LoadFromFile(pfmem);
      if memo1.Lines.Count=0 then memo1.Lines.Add('01.01.0001');
      label1.Text:=memo1.Lines[0];
      IdIMAP41.Connect(); - тут программа вылетает
      //ComboBox1.Items.LoadFromFile(pfprod);
      //ComboBox2.Items.LoadFromFile(pfpost);
      //loadlist;
      end;
      Задача проста: найти письмо и скачать вложение, для дальнейшей обработки.
      При запуске на Windows 8 все работает нормально, после установки apk и запуска на телефоне программа вылетает при IdIMAP41.Connect()
      Менял на pop3 тоже самое
      Подскажите пожалуйста в чем может быть проблема? Может есть другие варианты для загрузки почты?
      Заранее спасибо!
       
    • От Ufomaster
      Как из IdTCPServer обратиться к нужному клиенту IdTCPClient ?
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...