I'm writing a client-server application using TIdTCPClient/TIdTcpServer indy components in Delphi.
Data transfering usually works fine, but often I read wrong data from server; I get previous requests' answers, not current ones.
During debug, both apps are working locally, so there are no way for data to be lost during transfer.
Timeouts are 1000-3000 msec, this is far enough to avoid sending second requests before receiving answer on the first one.
I use simple data format: first 4 bytes is data packet length, the rest is binary data of that length.
The server-side code is (simplified for sending strings only; I also use binary buffers the same way, but this code is simpler to understand and check):
Var
lng: LongInt;
ib: TIdBytes;
begin
// Prepare data to send:
lng:=length(s);// s is an AnsiString to be sent
SetLength(ib,lng+4);
Move(lng,ib[0],4);
Move(s[1],ib[4],length(s));
// Send:
AContext.Connection.IOHandler.WriteDirect(ib);
end;
The client-side code for sending request is the same (calling TIdTcpClient.IOHandler.WriteDirect() in last line). The client-side code for reading server answer is:
Var
ib: TIdBytes;
size,done,lng: LongInt;
begin
Result:=false;
// answer length:
try
SetLength(ib,0);
tcp.IOHandler.ReadBytes(ib,4,false);
Move(ib[0],size,4);
if length(ib)<0 then Exit;// wrong data
except
on E: Exception do;// code skipped
end;
// read answer body:
done:=0;
b.Clear;// b is my buffer, TStream descendant
while done<size do
begin
lng:=Min(size-done,MaxBlockSize);
// read:
SetLength(ib,0);// to be sure
tcp.IOHandler.ReadBytes(ib,lng,false);
if length(ib)=0 then Exit;// error reading
// append my buffer:
b.Wr(ib[0],length(ib));
// progress:
Inc(done,length(ib));
end;
end;
The data exchange order is:
Client sends request to server,
Server reads the request and sends answer back to client,
Client reads the answer.
Wrong data appears on step 3.
Maybe I'm doing something generally wrong?
I've tried to ReadBytes() right before sending request to server to clear the incoming buffer, but that doesn't helps too, as many other things I've tried...
Now I'm just out of ideas :(
TIdTCPServeris a multi-threaded component. Each client runs in its own worker thread, not in the main thread. TheOnExecuteevent is triggered in the context of those worker threads. So it CAN process multiple clients in parallel, and as such you have to make sure your event handler code is thread-safe. - Remy Lebeau