LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Strange 'Caching' Behaviour on TCP Write?

Solved!
Go to solution

I've encountered some strange behaviour when attempting to send strings over a TCP connection.

 

Opening the TCP connection works fine (confirmed on the other device), but whenever I attempt to send a string I don't get the response I expect from the other device. When troubleshooting I found that the other device doesn't appear to be recognising that anything was sent by my VI.

 

More oddly, when I close the TCP connection from the VI, the other device suddenly 'gets' the string I sent, sends the response it should be sending, and then closes the connection on its end. Obviously, I don't receive the response on the VI end as it has already closed the connection. It feels like my VI is 'caching' the stuff I tell it to send and only actually sending it when it closes the connection. Now that I think about it, it may be that it only sends the last string I tried to send at the point of closing the connection, but I would need to check that when I'm in front of the device again to be sure.

 

I've gone as far as adding code to close the TCP connection immediately after sending the string, which has the same effect - but this hack clearly isn't going to cut it as I can't receive the device's responses. (Repeatedly opening and closing a TCP connection feels like bad practice anyway - but I'm no expert in this field.)

 

Does anyone have any input on this? Have I simply made a dumb mistake, or misunderstood the TCP protocol / the use of Labview's TCP VIs?

 

I haven't got a huge amount of experience with Labview and I'm early in my engineering career, so I don't want to go down the thought process of whether the client's device is misbehaving before being very sure that I haven't made mistakes on my end!

 

The VI I used to test the connection with the device I'm communicating with is attached (forgive the mess and poor structure, I put it together quickly to test the interfacing when my client dropped off their device).

0 Kudos
Message 1 of 15
(3,308 Views)
Solution
Accepted by topic author jrveale

It is probably not the issue, but you really need to learn to not use Local Variables so much.  I worry that you have a weird race condition where the Connection ID is being read before it is set and you are therefore using an invalid reference.

 

Start by looking into the Queued Message Handler.  This way you can command the reader loop when it can start reading instead of relying on the local variable.  You can also pass to it the Connection ID in the queue.  What I would do is use the timeout of the queue to decide when to attempt a read.  Store the timeout in a shift register so you can start with it at -1 (wait forever) and then change it to 200 when you get the command to start reading.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 2 of 15
(3,294 Views)

Hi, thanks for responding.

 

I actually came across the issue of rookie overuse of Local Variables earlier this morning, and I'm spending some time looking into QMHs. I can see now how LabVIEW is different to more conventional programming languages in this sense and how race conditions from local variable read/writes will affect my current project quite badly (it currently relies on a number of parallel state machines which are built simply from loops containing enumerated cases). So thanks for flagging this again for me.

 

I'm also not sure if this is the cause of the issue in this specific case though, I'll look into it.

0 Kudos
Message 3 of 15
(3,284 Views)

Further, I've realised that the structure I used in that test VI is borrowed from the attached demo project.

 

This is a piece of simple demo software provided by the manufacturer of a robot I'm using. You can see it works on the same principles as my attempt. As far as I can tell, this demo VI should have the same issues with race conditions as it has a nearly identical architecture - I can't really test this, however, as the supplier has yet to provide me with the robot itself!

 

It's just that I'm surprised that a supplier's demo VI includes such rookie mistakes.

0 Kudos
Message 4 of 15
(3,281 Views)

@jrveale wrote:

Further, I've realised that the structure I used in that test VI is borrowed from the attached demo project.

 

...

It's just that I'm surprised that a supplier's demo VI includes such rookie mistakes.


I would be surprised if a demo did NOT have rookie mistakes!

 

Look to examples for nothing more than the bare minimum required to talk to widgets. The examples provided are often put together by non-wireworkers that may be OK at text based languages but think they can just code LV as if it is another form of text based...

 

I one spoke to the support engineer that wrote the driver for a widget and I commented on his code making suggestions for improvement. He said "yes those examples are more an example of how to parse text in LV."

 

Now if you still have issues after you settle on a good architecture...

 

Be aware the Nagle Algorithm may be involved in delays in packet delivery, particularly if the packets are small.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 5 of 15
(3,274 Views)

The attached VI sets nodelay in windows (i.e. disables Nagle). It works well for small packet command/response type communication over TCP.

 

No, I didn't write it.

Message 6 of 15
(3,268 Views)

Your code really makes no sense. I wouldn't separate your write and reads between two loops. I would use a single state machine for handling your connection to the device. Also, you never read more than one byte of data. Why would you do this? Even if you had a terribly inefficient method of reading your data 1 byte at a time you never concatenate the data you read. After you read it you concatenate it with the shift register which you immediately replace with an empty string. Therefore you will never have more than one byte of data. You never update your Received Json control so you will never have anything to translate.

 

I would suggest you look at the examples that ship with LabVIEW for the basics of TCP and put everything for your connection handling into a single state machine. Start there and you will most likely have much better results.

 

Do you know if your data will be terminated? Does the data include a field indicating the amount of data which should be received?  If it does not have a distinct termination character you need to come up with a good method of determining when to stop reading. The method I use which has been very successful is to read a single character and have a reasonable timeout on the read. If this read timeouts I throw an error indicating I failed to get the expected response. Once I read that single character I will read fairly large blocks of data (this size depends somewhat on what you will expect to receive) and use a short timeout. When this timeouts I ignore this error and assume that I have received all of the data. I forward this data to my message parser and go on from there.

 

If your communication will always be in the form of a command and response then simply send the command and read the data after it. Then your state machine can wait until you needs to send the next command. If you will also be receiving unsolicited data than your need to have your state machine alternate between looking for incoming data and new commands to send. 



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 7 of 15
(3,255 Views)
Message 8 of 15
(3,246 Views)

 


non-wireworkers that may be OK at text based languages but think they can just code LV as if it is another form of text based... 

This is essentially a summary of my code so far in LabVIEW.

 

Thanks for the heads up on Nagle, I'll look into it!

Message 9 of 15
(3,243 Views)

@jrveale wrote:

 


non-wireworkers that may be OK at text based languages but think they can just code LV as if it is another form of text based... 

This is essentially a summary of my code so far in LabVIEW.

 

Thanks for the heads up on Nagle, I'll look into it!


Thank you for your honesty, fessing up to your sins AND for progressing to the point where you have learned how to spell LabVIEW. (smiley-wink)

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 10 of 15
(3,238 Views)