![]() |
Reading returned data via TIdTcpClient? - Printable Version +- Atozed Forums (https://www.atozed.com/forums) +-- Forum: Indy (https://www.atozed.com/forums/forum-8.html) +--- Forum: Indy General Discussion (https://www.atozed.com/forums/forum-9.html) +--- Thread: Reading returned data via TIdTcpClient? (/thread-17.html) |
Reading returned data via TIdTcpClient? - BosseB - 03-15-2018 I am always struggling with this whenever I try to throw together a TCP client application... I can easily send commands to the server (in this case a WiFi IoT module. I know it responds to the command but for the life of me I cannot get the reply. The platform I use is 64 bit FreePascal 3.0.4 + Lazarus 1.8.0 with the IndyLaz package installed THe function that fails to work as I hoped looks like this (FComm is a TIdTcpClient object): Code: function TConfigCommHandler.GetItem(Cmd: TIdBytes; var Data: TIdBytes): boolean; I try to detect it via the ETX check but since the data is only at maximum some 25-40 bytes (not possible to know beforehand) I thought it highly unlikely it would be split between packets... I found the cause regarding this specific problem: The server did not add the trailing ETX to replies, so all of them were thrown away. I modified the server code to always add the ETX to all outgoing messages. But I have a follow-up question: How can the PC application be made such that it will catch and display all incoming data without first sending a command? For example spontaneous messages from the device are also interesting... RE: Reading returned data via TIdTcpClient? - rlebeau - 03-16-2018 (03-15-2018, 06:53 PM)BosseB Wrote: I can easily send commands to the server (in this case a WiFi IoT module. What does the response actually look like? If you can't read a response, it is usually because you are not reading it correctly. (03-15-2018, 06:53 PM)BosseB Wrote: When you call TIdIOHandler.ReadBytes() with AByteCount=-1, you are asking it to return whatever arbitrary bytes are currently available at that moment, waiting up to the ReadTimeout for new bytes to arrive. Prior to SVN rev 5372 (Oct 6 2016), ReadBytes() with AByteCount=-1 would ALWAYS read from the socket, even if there were already bytes left over in the InputBuffer from a previous read. From rev 5372 onwards, ReadBytes() with AByteCount=-1 reads from the socket ONLY if the InputBuffer is empty. (03-15-2018, 06:53 PM)BosseB Wrote: If the response data is ALWAYS terminated by an ETX, then I would not suggest using ReadBytes() with AByteCount=-1 at all. If the data is textual in nature, you can use TIdIOHandler.ReadLn() or TIdIOHandler.WaitFor(). Both will allow you to specify ETX as a terminator, and will wait for the ETX to arrive before then returning everything that precedes it. If the data is binary in nature, TIdIOHandler doesn't have similar methods for bytes, but it would not be hard to implement manually in your code, eg: Code: function TConfigCommHandler.GetItem(const Cmd: TIdBytes; var Data: TIdBytes): boolean; (03-15-2018, 06:53 PM)BosseB Wrote: For example what happens if this ReadBytes function does not get all of the incoming bytes? It will return what it can, and you will have to call it again to read more bytes. (03-15-2018, 06:53 PM)BosseB Wrote: I try to detect it via the ETX check but since the data is only at maximum some 25-40 bytes (not possible to know beforehand) I thought it highly unlikely it would be split between packets... With TCP, it very well can be. Just because messages are small doesn't mean they can't be split up into multiple network packets. (03-15-2018, 06:53 PM)BosseB Wrote: I found the cause regarding this specific problem: Good. (03-15-2018, 06:53 PM)BosseB Wrote: How can the PC application be made such that it will catch and display all incoming data without first sending a command? You would need to run a continuous reading loop, such as with a timer or worker thread, and then display whatever you receive. In that kind of situation, using ReadBytes() with AByteCount=-1 would make more sense. Unless the messages have a structure to them, then it is best to read the structure (like above, reading until ETX is reached), and then display only complete messages. (03-15-2018, 06:53 PM)BosseB Wrote: For example spontaneous messages from the device are also interesting... Dealing with unsolicited messages is always fun ![]() |