Как получить строку ответа с сервера Indy udp? - PullRequest
0 голосов
/ 02 мая 2019

Я пытаюсь создать простой текстовый обмен между Indy UDP-клиентом и сервером в C ++ Builder 10.3.1. Это код, который я использую:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    IdUDPClient1->Send("Hello");
    UnicodeString resp = IdUDPClient1->ReceiveString();
    ShowMessage(resp);
}

void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread,
    const TIdBytes AData, TIdSocketHandle *ABinding)
{
    UnicodeString req = BytesToString(AData);

    if(req == "Hello"){
        // why this don't work?
        ABinding->Send("Hello 2");

        // the following works if ThreadedEvent = true
        // AThread->Server->Send(ABinding->PeerIP, ABinding->PeerPort, "Hello 2");
    }
}

Я не могу получить ответ от сервера на стороне клиента. Что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 03 мая 2019

На стороне сервера предоставленное TIdSocketHandle в событии OnUDPRead не «подключено» (с точки зрения ОС) к одноранговому узлу, который отправил полученные данные, поэтому по умолчанию для вызова ABinding->Send() требуется указание целевого IP / порта для отправки. Вот почему ABinding->Send(ABinding->PeerIP, ABinding->PeerPort, "Hello 2"); работает, а ABinding->Send("Hello 2"); - нет.

Вызов ABinding->Send() не зависит от свойства ThreadedEvent сервера любым способом. Это свойство просто контролирует, запускается ли событие сервера OnUDPRead в контексте в основном потоке пользовательского интерфейса или нет. не влияет на то, как сервер выделяет и управляет своими сокетами.

Однако, если свойство ThreadedEvent сервера имеет значение false и клиент и сервер работают в одном и том же процессе приложения, сервер не сможет запустить событие OnUDPRead, пока работает Button1Click(). В этой ситуации вам нужно будет установить для ThreadedEvent значение true, чтобы вместо этого OnUDPRead вызывалось в контексте рабочего потока, а не в основном потоке пользовательского интерфейса.

В противном случае переместите клиент в его собственный рабочий поток.

1 голос
/ 02 мая 2019

Надеюсь, что вы можете принять ответ в Delphi.Я не могу перевести это только сейчас.

С парой проектов, VclIdUDPServer и VclIdUDPClient, следующим образом, я получаю два для общения.Испытано на одной машине, а также на двух машинах.Обратите внимание, что это минимальный код для того, чтобы заставить двоих общаться в чате.

VclIdUDPServer

procedure TForm1.FormCreate(Sender: TObject);
var
  Binding: TIdSocketHandle;
begin
  Binding := IdUDPServer1.Bindings.Add;
  Binding.IP := '192.168.2.109';
  Binding.Port:= 49000;
  IdUDPServer1.OnUDPRead:= IdUDPServer1UDPRead;
  IdUDPServer1.Active:=True;
end;

procedure TForm1.IdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var
  req: string;
begin
  req := BytesToString(AData);
  Memo2.Lines.Add(req);
  if req = 'Hello' then
    ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, 'Yes sir!', ABinding.IPVersion);
  end;
end;

VclIdUDPClient

procedure TForm2.FormCreate(Sender: TObject);
begin
  IdUDPClient1.Host:='192.168.x.xxx'; // set to your ip
  IdUDPClient1.Port:=49000;
  IdUDPClient1.Active:=True;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  rep: string;
begin
  IdUdpClient1.Send('Hello');
  rep := IdUdpClient1.ReceiveString();
  Memo1.Lines.Add(rep);
end;
...