Forum > Ported from Delphi/Kylix

Indy Client in a Thread

<< < (2/3) > >>

Remy Lebeau:

--- Quote from: JimKueneman on October 27, 2023, 04:23:20 am ---The Client on the other hand never sees the message...
...

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---if not IdTCPClient.IOHandler.InputBufferIsEmpty then 
Always returns false.

--- End quote ---

That is because the InputBuffer is filled with data only when a read operation is performed on the underlying socket, which CheckForDataOnSource() does.  Indy doesn't read from the socket until you tell Indy to read something.  Most of the higher-level reading methods, like ReadStream(), handle this internally for you, checking and filling the InputBuffer until the requested data becomes available in full.


--- Quote from: JimKueneman on October 27, 2023, 04:11:14 pm ---This seems to have solved it for now...

--- End quote ---

Typically, you don't need the InputBufferIsEmpty() check, just call a reading method like ReadStream() unconditionally and let it block the calling thread until the requested data arrives, eg:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TLccEthernetClientThread.OnThreadComponentRun(Sender: TIdThreadComponent);var  ...begin       ReceiveStreamConnectionThread.Size := 0;  idTCPClient.IOHandler.ReadStream(ReceiveStreamConnectionThread, DesiredSize);  ... end;    
The CheckForDataOnSource()/InputBufferIsEmpty() approach is mainly used only when either:


* the calling thread does not want to be blocked and wants to do other things even when data is not available.
* the calling thread does not know how much data is being sent to it (as in your example).
In the latter case, unless you are writing a proxy or streaming media, not knowing how much data to read is generally a sign of bad protocol design.

JimKueneman:
Thanks for the explanation.  The protocol was really aimed at CAN bus transfer but a "cheap" TCP adaptation of it has started to gain traction by sending strings (which I am trying to stop and use a TCP specific protocol).

Thanks again.
Jim

Remy Lebeau:
I'm not familiar with CAN bus, but I would be very surprised if it doesn't specify proper data sizes in its payloads.  You should be parsing the CAN bus messages to determine how to read them correctly, not just blinding reading arbitrary amounts of bytes, as your earlier example was doing.

JimKueneman:
Unfortunately the way the protocol was implemented in TCP it does not.. the payload could be from 0 to 8 bytes and you don't know until you find a null character.    The TCP protocol I am trying to push for will have the ability to read directly into the message header and read how many bytes are in the payload (and will be way bigger than 8 bytes... the way it is not is terribly slow as the messages need to ACK back and forth carrying only up to 8 bytes (a CAN limitation).  Then I can just read a known header size and then a known payload size but till then I can only do what others have implemented.

JimKueneman:
Remy are

procedure IdTCPServerExecute(AContext: TIdContext);

connections serialized calling this function?  I am having this strange hard to reproduce bug with a stream I am using for a read in the function.  It seems like the Size is changing in the middle of a for loop when I am iterating through it within this function but I have not been able to catch it when I add a bit of code to test for it.

Jim

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version