Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can know length of readstring in Idtcpserver
#5
(08-30-2021, 01:32 AM)Zsanvs Wrote: I found each JSON message start with {"devId":"492C201010012591"  ,is it possible to split message by use ReadLn() ?

Since that is the start of each message, not the end, I would use that string with TIdIOHandler.WaitFor() instead.  But that won't tell you where each message ends.  You should not have to wait for the beginning of the next message before processing the previous message.

(08-30-2021, 01:32 AM)Zsanvs Wrote: or as you mentioned another option buffer function, please give me some coding for your solution if it's possible . Smile it's hard for me to find some demo online.

See further below.

(08-30-2021, 02:51 AM)Zsanvs Wrote: Thank you for your option of Buffer, I think i have found solution :

That is not a good solution, for many reasons:
  • If the IOHandler.InputBuffer is empty, you are not reading more bytes into it.  You stop reading when there are no more bytes in the buffer.  But what if the device sends a lot of messages in a short time?  In any case, you could have replaced that entire loop with a single call to IOHandler.InputBufferAsString() instead.
  • Not that it matters, because this code still doesn't try to detect the actual end of each message properly.
  • IOHandler.ReadString() reads and decodes the specified number of bytes into Characters.  You are reading only 1 byte at a time, not 1 Character at a time. So that will work only for single-byte Characters, but will fail on multi-byte characters, like non-ASCII characters encoded in UTF-8.  If you really want to read 1 Character at a time, use IOHandler.ReadChar() instead of IOHandler.ReadString().  But it will still fail on Unicode characters > U+FFFF.
  • This code runs in a worker thread, so you MUST synchronize with the main UI thread when touching UI controls, like your TMemo.

So, again I ask you, what is the actual protocol that the IOT device is using on the wire?  Do you have any documentation for that?  If not, then can you at least capture a session containing multiple messages? Either with a packet sniffer like Wireshark, or by assigning one of Indy's TIdLog... components to the IOHandler.Intercept property.

In the meantime, try something more like this:

Code:
var
  Level, BufSize, StartPos, I: Integer;
  str: string;

...

AContext.Connection.IOHandler.WaitFor('{"devId":', False);

BufSize := AContext.Connection.IOHandler.InputBuffer.Size;
StartPos := 1;
Level := 1;

repeat
  while (StartPos < BufSize) and (Level > 0) do
  begin
    case AContext.Connection.IOHandler.InputBuffer.PeekByte(StartPos) of
      Ord('{'): Inc(Level);
      Ord('}'): Dec(Level);
    end;
    Inc(StartPos);
  end;
  if Level = 0 then Break;
  AContext.Connection.IOHandler.CheckForDataOnSource(100);
  AContext.Connection.IOHandler.CheckForDisconnect(True, True);
until False;

str := AContext.Connection.IOHandler.ReadString(StartPos);
TThread.Synchronize(nil,
  procedure
  begin
    Memo1.lines.Add('ReceiveString-> :' +str);
  end
);

Reply


Messages In This Thread
RE: How can know length of readstring in Idtcpserver - by rlebeau - 08-30-2021, 06:06 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)