开发者

Indy, How to know size of buffer needed?

开发者 https://www.devze.com 2023-02-15 05:12 出处:网络
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...

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;
0

精彩评论

暂无评论...
验证码 换一张
取 消