TCPSocket DataAvailable handling

Good afternoon (o;

New simple project here communication with measuring devices over TCP…

Now how do you handle the DataAvailable event when you don’t know how many data is returned?

Just fire a Timer when Connected fires, use ReadAll to internal buffer and use the buffer after a specific time elapsed?

No Timer needed. Just put the ReadAll command in your DataReceived event and accumulate a buffer that way. Every time you add data to the buffer, you can inspect it to see if there is enough to process - for example, if you’ve received a completed packet of data - and react accordingly.

The example above I tried sends a command to the scope to return a PNG image…and the DataReceived fired at least twice…so would get complicated to know if all data is received as it would mean digging deep into PNG format…

I guess I stick with raw data returned as I used in the past with my PyQt5 app I did as the Rigol displays waveforms rather ugly and filters out small spikes…my old Yokogawa scope displays much better waveforms.

The PyQt5 I intend to port to Xojo (waveforms are drawn by raw values returned):

Not at all. Send the size (number of bytes) of your picture before sending the picture. The other size receives this information and waits until the buffer has the correct length.

I can’t tell the Rigol scope to send the length of the PNG in advance…it just sends it prepended with 11 bytes containing the serial number (o;

I’ll stick with raw text data returned…that would also allow me to resize the window/canvas and always have the perfect waveform instead of scaled PNG…

Yeah, don’t do that. DataAvailable events are reentrant which means the event could be called again while you are processing data in the previous call.

My go to solution is to use an array of strings and to simply put in the DataAvailable event:

BufferArray.Add me.ReadAll

Then you have a timer where you check to see if the number of items in the array is > the last time you processed data. If it is, you try processing again.

Hi Richard
The number of bytes to receive is found in the first TCM header bytes in the first 12 bytes.
I’m doing this in the dataAvailable event to handle this case on my Rigol Oscilloscope:

dim s as string = me.Lookahead().left( 12 )

if s.left(1) = “#” then
dim nrheadchar as integer = val( s.left(2).right(1) )
RecBuff( 0 ).nrBytes = val( s.left(nrheadchar + 2 ).right( nrheadchar ) )
end if

if me.BytesAvailable < RecBuff( 0 ).nrBytes then
return
end if

The Rigol documenations defines the TMC header as:

The read data format is TMC header + binary data stream of the screenshot +
terminator. The TMC header is in #NXXXXXX format; wherein, # is the TMC header
identifier; N following # represents the number of digits (in the decimal integer) that
follow; the length of the binary data stream of the screenshot is expressed in ASCII
strings, and the terminator represents the ending of communication. For example, the
data read for one time is #9000387356. 9 indicates the number of digits (in the
decimal integer) that follow, and “000387356” indicates the length of the binary data
stream, that is, the number of bytes to be transmitted.

/Håkan N

I have a similar situation (reading raw data from TCP socket). In the DataAvailable event I append the result of me.ReadAll to a buffer string.

It then calls Thread.Start or Thread.Resume (thread could be paused waiting for more data). Which then spins off to go process the data outside of the main thread.

In the processing thread it splits the data on a delimiter and then sets the buffer string to the last item in the array if got split in the middle.

Are you saying that there is a possible condition where things could get messed up if there is another event between the split and the append or is this a safe way to do things?

Yeah…figured that out my self when I studied the Rigol programming manual (o;

Have to test if the Rigol would allow multiple TCP connection to speed things up…but so far I’m happy with the progress (o;

1 Like