Server:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
len : integer;
rest_packet : string;
packet_length : string;
begin
try
// length 10, it will be the rest packet length: 0000000545
// So the bug is in ReadBytes(10) , some times it do not receive the length 0000000015 but receive a mix of data+length, something like: "00015Hello" or "loWorldApp" etc.
packet_length := AContext.Connection.Socket.ReadString(10);
except
on E:Exception do begin Exit; end;
end;
// Convert string to int: 0000000545 , to 545
try
len := StrToInt(packet_length);
except
on E:Exception do begin Exit; end;
end;
// get reset of data, size: 545
try
rest_packet := AContext.Connection.Socket.ReadString(len);
except
on E:Exception do begin Exit; end;
end;
Client:
Client is sending data in multithreading to server, about 13 clients is sending data to server thrue one Socket connection. Clients are sending data like this:
EnterCriticalSection(CS);
// Memo1.Lines.Add(packet); // i can see here that all works fine.
Ftunnel.Socket.Write(packet);
LeaveCriticalSection(CS);
CS - is global, and created like this:
initialization
InitializeCriticalSection(CS);
finalization
DeleteCriticalSection(CS);
Structure of the packet is:
LengthDATA
example:
0000000015HelloWorldApple
So the bug is in ReadBytes(10) , some times it do not receive the length 0000000015 but receive a mix of data+length, something like: "00015Hello" or "loWorldApp" etc.
Why this is happening, what I'm doing wrong ?
ReadTimeout is default -1
Here how is look Client code:
procedure ss_thread.Execute;
var ss : TIdTCPClient;
unix_time : integer;
data : TIdBytes;
packet, s : string;
begin
// connecting to website to get a data
ss := TIdTCPClient.Create(nil);
try
with TIdTcpClient(ss) do
begin
Host := '127.0.0.1';
Port := 80;
Connect;
end;
except
on E:Exception do
begin
ss.Disconnect;
exit;
end;
end;
// writing a data from server to connected web site server
try
ss.Socket.Write(Fff_data);
except
on E:Exception do begin end;
end;
unix_time := DateTimeToUnix(NOW);
// getting data from web site server, all looks thread safe?
while True do
begin
ss.Socket.CheckForDataOnSource(5);
if not ss.Socket.InputBufferIsEmpty then
begin
SetLength(data, 0);
ss.Socket.InputBuffer.ExtractToBytes(data);
s := TIdEncoderMIME.EncodeBytes(data);
packet := make_my_length(s) + s;
ss.Socket.InputBuffer.Clear;
unix_time := DateTimeToUnix(NOW);
try
// sending data from web site, to server
EnterCriticalSection(CS);
tunnel.Socket.Write(packet);
LeaveCriticalSection(CS);
except
on E:Exception do begin end;
end;
end;
// disconnecting if no more data for 120sec
if (DateTimeToUnix(NOW) - unix_time) > 120 then
begin
ss.Disconnect;
break;
end;
// killing thread if web site server disconnected us
if not ss.Connected then
begin
break;
end;
// disconnecting from web site server and killing thread if tunnel died
if not tunnel.Connected then
begin
ss.Disconnect;
break;
end;
end;
// terminate thread
Terminate;
end;
make my length code, works good:
function make_my_length(s:string):string;
var len, i : integer;
res : string;
begin
if s='' then
begin
Result := '';
Exit;
end;
res := '';
len := Length(s);
if len < 10 then
for i:=1 to (10 - len) do
begin
res := res + '0';
end;
Result := res + s;
end;
Delphi 2010, Indy 10, Win7
make_my_length()does not need to be a member of the class. It does not access any other class members. It accepts an input String an only operates on that value. That is thread-safe. - Remy Lebeau