I have some problem when using Indy (idTCPServer component) to read data send by client, the data itself was a hex formatted so i can't use AThread.Connection.ReadLn(); for that...
Here my sample data sended by client
24 24 00 11 12 34 56 FF FF FF FF 50 00 8B 9B 0D 0A
or
24 24 00 13 12 34 56 FF FF FF FF 90 02 00 0A 8F D4 0D 0A
PS: it's in bytes hexadecimal (data length may vary depend on command, at maximum 160 bytes) which i can't get string representation since $00 translated to null (which mean i can't use ReadLn)
Here my sample code
procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
Msg : Array[0..255] of Byte;
begin
AThread.connection.ReadBuffer(Msg,SizeOf(Msg));
AThread.connection.WriteBuffer(Msg,MsgSize,true);
end;
this code will not work if client not send 255 byte data, while in my case data length can be vary, i have tried this, but no response outputted
procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
Msg : Array of Byte;
MsgSize : integer;
begin
MsgSize := AThread.connection.ReadInteger; //doesn't actually get packet length?开发者_高级运维
SetLength(Msg, MsgSize);
AThread.connection.ReadBuffer(Msg,MsgSize);
AThread.connection.WriteBuffer(Msg,MsgSize,true);
end;
so how exactly i can count how many byte data sended by client (packet length)? or could someone tell me the right code to read the data?
The simple answer is: you can't. TCP is a stream protocol, so there is no concept of a message. The data is received in chunks, whose sizes may (and will) differ from the actually sent buffers (the network stack is free to slice or merge the stream at will).
You may built a message protocol on top of TCP, e.g. by starting the transmission, and every consequent message, by a "size field" and then waiting only for the bytes needed; you still need to check the actual size received and re-reading the rest if applicable.
The point is: packet length in the TCP world has nothing to do with the length of the sent messages.
What TIdTCPConnection
does behind all the Read
-methods is:
reading all available data from the network stack, appending it into an internal input buffer and returning the requested N bytes from the beginning of the buffer, if available (waiting for next chunk, if not).
The 3rd and 4th bytes in the data you have shown specify the total size of the data being sent. You were close to try ReadInteger()
, but the way you used it includes the 1st and 2nd bytes, which is wrong. Try this instead:
procedure TfrmMain.IdTCPServerExecute(AThread: TIdPeerThread);
var
Unknown: Smallint; // maybe a msg type?
DataSize: Smallint;
Data: Array of Byte;
begin
Unknown := AThread.Connection.ReadSmallInt;
DataSize := AThread.Connection.ReadSmallInt - 4;
SetLength(Data, DataSize);
AThread.Connection.ReadBuffer(Data[0], DataSize);
//...
end;
精彩评论