A TCP server is sending data frames continuosly every 8ms. I want to program a client able to receive these data frames. Is there any procedure in Indy 9 to know if there is data available in the buffer?
My current programs is the following (I am using a 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;
Is there any more efficient solution for reading TCP data continuously (like onread event in UDP)?
Thanks in advance.
TIdTCPClient
is not an asynchronous component. It does not tell you when data arrives. You need to use a Timer or a Thread to periodically poll the socket for new data (TIdUDPServer
uses an internal thread to trigger its OnUDPRead
event), eg:
procedure TForm1.Button1Click(Sender: TObject);
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;
With that said, CurrentReadBuffer()
is generally not the best choice to use. Typically you would do something more like this instead:
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;
Update: given new information about the frame structure and your switch to a thread, you should be doing this instead:
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;