LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Strange 'Caching' Behaviour on TCP Write?

Solved!
Go to solution

Your code really makes no sense.


I mean, yes, you're right. The short answer is that I ripped this VI out of a larger system where some (but certainly not all) of these strange choices do make some sense.

 

The longer answer is:

 

Yes, I should use a single state machine for both read & write - in the full application I'll be expecting both command and response and out-of-the-blue messages. Originally, based on a (seemingly poor) demo VI, I thought it would be best to then read constantly in machine, and write when necessary in-line with a main state machine. I can see why instead having a read/write machine which communicates with the main state machine is preferable.

 

Reading one byte at a time is bad. And the concatenation is from the full application but I think not really an issue for this test VI, as each byte is written to the end of the Message Log Control.

 

Never updating the Received JSON Control was intentional laziness, for the purposes of the test I just copy & paste the relevant string from the message log.

 



When this timeouts I ignore this error and assume that I have received all of the data 

Makes sense to me!

 

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. 

The need to stop trying to read while writing wasn't immediately obvious to me, thank you.

 

Looking back, the shortest answer is I worked from a bad example and came up with a bad system.

 

Thanks for taking the time to answer.

0 Kudos
Message 11 of 15
(475 Views)

@crossrulz wrote:

...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...


I believe that this was my issue (though I've also turned off Nagle). Thanks for the input!

 

You'll be happy to know that I'm now running through converting my current project's code away from overuse of local variables.

 

I've attached my working solution in case this helps anyone else in the future. I'm sure there are other bad practices in it - but it is my attempt to atone for previous sins.

Message 12 of 15
(458 Views)

First, avoid wires running other objects as well as running backwards. It makes the code harder to read and follow.

 

I see no reason why you are using a queue to hold your received messages. Simply use an array. You still don't need to read a single byte at a time looking for your end of line. Just read a block at a time. Though the one benefit of reading the single character at a time is that you will not have to wait for the timeout since you should find the end of line without encountering the timeout. You will not detect a missing end of line if your data must contain it. This method works well for cases when you don't know how much data will be receiver and it does not contain a delimiter. If a delimiter is there, use that.

 

There is no reason to have two queues for the lower loop state and data to send. Use a single queue and create a message which will contain the desired state as well as any data needed by that state. When you need to send data simply queue up the send state with the data to send. The send state will then queue the receive state. You will avoid the convoluted logic of waiting for an timeout error on your read in order to actually send the data. The code can definitely be cleaned up.

 

Kudos for working to remove all of the local and global variables in your code.



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 13 of 15
(449 Views)


Simply use an array.

Oops, I clearly over-complicated there.

 


There is no reason to have two queues for the lower loop state and data to send. Use a single queue and create a message which will contain the desired state as well as any data needed by that state.


Ah, I can see that saves a mess of wires, I assume the best way of achieving this is by queuing clusters that contain both the Control & a String?

 

When you need to send data simply queue up the send state with the data to send. The send state will then queue the receive state. You will avoid the convoluted logic of waiting for an timeout error on your read in order to actually send the data.

It took me a minute to understand this, but I definitely see the benefit now. Interestingly, this convoluted logic of waiting for a timeout error comes right out of LabVIEW's "TCP Multiple Connections" example project. There must be some reasoning for its use in that scenario?

 

Thanks again.

0 Kudos
Message 14 of 15
(443 Views)

Yes, just queue up clusters which contain your state (either ENUM or string, I generally prefer ENUMs) and something to contain the data. If all of your data is the same you can use that specific type. If you will have different data types in messages you can use either a string or a variant. The receiver will need to convert that back into the specific data type but that is easy since it will know what type of data it is expecting.



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
0 Kudos
Message 15 of 15
(434 Views)