Перейти к содержанию
Fire Monkey от А до Я
  • 0

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


Wovan2

Вопрос

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

Борюсь с 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

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

 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
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
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 эмодзи.

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

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

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

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