Frage an tcp, indy-9, tcpclient, indy – Indy TCP - Daten in einer Schleife lesen

2

Ein TCP-Server sendet kontinuierlich alle 8 ms Datenrahmen. Ich möchte einen Client programmieren, der diese Datenrahmen empfangen kann. Gibt es eine Prozedur in Indy 9, um zu wissen, ob Daten im Puffer verfügbar sind?

Meine aktuellen Programme sind die folgenden (ich verwende einen Thread):

procedure TThreadRead.Execute;
var
  buffer: array [0..755] of byte;
  //s1: string;
  //i: integer;
begin
  IdTCPClient1.RecvBufferSize:= 756;
  IdTCPClient1.Connect;
  while Terminated = false do
  begin
    if IdTCPClient1.InputBuffer.Size = 0 then
       IdTCPClient1.ReadFromStack(True,0,False);
    while IdTCPClient1.InputBuffer.Size > 0 do
    begin
       ReadBuffer(buffer, FClient.InputBuffer.Size);
       //s1:= '';
       //For i:=0 To Length(buffer)-1 Do
       //  s1:=s1+IntToHex(Ord(buffer[i]),2); //Read values-->global var
       //Form1.Memo1.Text:=s1;
    end;
  end;
end;

Gibt es eine effizientere Lösung zum kontinuierlichen Lesen von TCP-Daten (wie bei einem gelesenen Ereignis in UDP)?

Danke im Voraus.

Deine Antwort

1   die antwort
5

TIdTCPClient ist keine asynchrone Komponente. Es sagt Ihnen nicht, wann Daten ankommen. Sie müssen einen Timer oder einen Thread verwenden, um den Socket regelmäßig auf neue Daten abzufragen (TIdUDPServer verwendet einen internen Thread, um seine auszulösenOnUDPRead Veranstaltung), zB:

begin
  IdTCPClient1.Connect;
  Timer1.Enabled := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Timer1.Enabled := False;
  IdTCPClient1.Disconnect;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  s1: string;
begin
  s1 := IdTCPClient1.CurrentReadBuffer;
  ...
end;

Nachdem das gesagt worden ist,CurrentReadBuffer() ist im Allgemeinen nicht die beste Wahl. Normalerweise würden Sie stattdessen etwas Ähnliches tun:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;

  IdTCPClient1.ReadFromStack(True, 0, False);

  while IdTCPClient1.InputBuffer.Size > 0 do
  begin
    // read one complete frame and process as needed ...
  end;

  Timer1.Enabled := True;
end;

Aktualisieren: Wenn Sie neue Informationen über die Frame-Struktur und Ihren Wechsel zu einem Thread erhalten haben, sollten Sie dies stattdessen tun:

procedure TThreadRead.Execute;
var
  buffer: array of Byte;
  numbytes: Integer;
begin
  SetLength(buffer, 0);
  IdTCPClient1.Connect;
  try
    while not Terminated do
    begin
      numbytes := StrToInt(' + IdTCPClient1.ReadString(8)) - 8;
      if numbytes <> Length(buffer) then
        SetLength(buffer, numbytes);
      if numbytes > 0 then
        IdTCPClient1.ReadBuffer(buffer[0], numbytes);
      // process buffer up to numbytes as needed...
    end;
  finally
    IdTCPClient1.Disconnect;
  end;
end;
Ich habe meinen ersten Beitrag mit dem aktuellen Programm aktualisiert, das ich verwende. Der TCP-Server sendet Frames mit 756 Bytes. Ich erhalte korrekte Frames (der Header ist immer derselbe). Nach dem Empfang mehrerer Bilder (zwischen 200 und 1000) erhalte ich jedoch ein letztes Bild mit einer Größe von weniger als 756 und erhalte nicht mehr Bilder. Ich muss eine TCP-Verbindung trennen und erneut herstellen, um die Daten erneut zu empfangen. Dieser Fehler tritt auch bei Verwendung von Timern anstelle eines Tthreads auf. user1361263
Ich habe meine Antwort dementsprechend aktualisiert, allerdings umso früherInputBuffer.Size Der Überprüfungscode hätte gut funktionieren sollen. Remy Lebeau
Es klingt so, als ob der Wert des Headers die Länge des Headers selbst enthält. Wenn ja, dann müssen Sie beim Aufruf 8 abziehenReadBuffer(). Ich habe meine Antwort entsprechend aktualisiert. Remy Lebeau
Der von Ihnen angezeigte Code missbraucht immer noch denInputBuffer, aber Sie haben noch nicht gezeigt, wie die Rahmenstruktur tatsächlich aussieht, und ich kann Ihnen nicht zeigen, wie Ihr Lesecode aussehen muss. Ich bitte Sie noch einmal zu zeigen, wie die Rahmen aussehen. Die Tatsache, dass der Server einen kleineren Frame sendet, ist wahrscheinlich ein Hinweis darauf, dass dem Server einfach die zu sendenden Daten ausgehen. Geben Sie weitere Informationen zur Funktionsweise der Frames an, unabhängig davon, wie der Code sie lesen soll. Remy Lebeau

Verwandte Fragen