LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

tcp/ip confusion

I would like to send TCP/IP messages between a client/server via localhost::port - I will eventually like to have a message that I send that contains a Length, ID, Version (might use ths to distinguish between similar products), and data.  All messages will have the length/ID,version, but the data may or may not exist (depending on the message), and it can vary in length.  The attached VI is a modified version of a <labview> example VI for TCP/IP client.  I plan on sending the carriage return and line feed in the client, and the TCP Read (at the server) is using the CR/LF mode.  I would like to perform one write and one read (on the other end).  Here's one of the problems I'm having.

 

In the attached code sample, I convert my length (I16) to a string using the "Number to hexadecimal string".  I do the same for the other test fields, concatenate the strings, append a carriage return and line feed, then issue a TCP Write.  On the other end, when I look at the string, (say I sent a length of '2'), a 50 (decimal) shows up (one byte).  If I have a length of 136 bytes, a '49', '51', '54' will be sent (3 bytes).  This applies to all the fields, but focusing on the length field for now, how do I know how many characters (when doing the read) make up the length field?  Do I have to pad certain fields to guarantee how many characters make up that field?

0 Kudos
Message 1 of 8
(4,407 Views)
If you will be using binary data you cannot use the line termination to delineate the end of the data. You must read the length from the data and then read that amount of data. Is there a reason you want to use only a single read/write? You can create a subVI that contains the multiple read/write calls and at the higher level it will appear as a single read/write. Any time you have binary data that can be any value. You should not try to use a termination character to terminate your data since this value can appear in the middle of a message.


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 2 of 8
(4,403 Views)
So you recommend more the approach where two writes/reads occur?  Based on the MsgID (assuming there is one in each message), would I then have to do the type cast / flatten technique to get each field into its properly sized variable?
Download All
0 Kudos
Message 3 of 8
(4,395 Views)

mrbean wrote: 

In the attached code sample, I convert my length (I16) to a string using the "Number to hexadecimal string".  I do the same for the other test fields, concatenate the strings, append a carriage return and line feed, then issue a TCP Write.  On the other end, when I look at the string, (say I sent a length of '2'), a 50 (decimal) shows up (one byte).  If I have a length of 136 bytes, a '49', '51', '54' will be sent (3 bytes).  This applies to all the fields, but focusing on the length field for now, how do I know how many characters (when doing the read) make up the length field?  Do I have to pad certain fields to guarantee how many characters make up that field?


I think you're misunderstand something here.  You do not want to use "Number to Hexadecimal String."  You want to use Typecast.  There's no need to convert a number into an ASCII string of an unknown length.  Although TCP Write expects a string, that string doesn't have to be actual text, it's just a series of bytes.  If you typecast an I16 to a string, it will always be exactly 2 bytes (with no loss of information).  On the other end you do the typecast the other way around - split out the first two characters and typecast back to I16.  This makes the data a fixed length, solving your problem.

0 Kudos
Message 4 of 8
(4,377 Views)
If I replace the number to hex with the typecast, do I then concatenate each typecast output (string) into one string that feeds into the TCP Write?  On the other end, how would I split out the first two characters and typecast to I16?
0 Kudos
Message 5 of 8
(4,372 Views)
Yes, you can concatenate the typecast outputs together.  To split the string when you read it, the easiest thing to do is to read only the right number of bytes and use that output - so, if you're reading a 2-byte length (I16), you read 2 bytes, typecast that to an int, and use the output as the length input to the next TCP read.  You can then take those bytes and do whatever you want to them - most commonly, typecast to a cluster or unflatten from string.  Of course if you want a complicated approach you can instead use string subset to get the bytes you want.
Message 6 of 8
(4,365 Views)

You asked "Is there a reason you want to use only a single read/write?"

 

I guess my concern is that if I do the two-read approach on the one end (which I've switched to now), the other end has to implement a two-write method, correct?  Right now, I have control of both ends, so that's not an issue.  If we had a third party vendor that wanted to send in messages, they would have to follow this same technique, right.  So, I guess if I state all of this in the ICD, then it's gospel.

0 Kudos
Message 7 of 8
(4,347 Views)

mrbean wrote:

 

I guess my concern is that if I do the two-read approach on the one end (which I've switched to now), the other end has to implement a two-write method, correct?


Not quite correct.  You're confusing protocol with implementation.  If your protocol says "All messages begin with a 4 byte length" then the other end can handle that however they want.  If they prefer they can prepend the length to the data and send it in a single write rather than two - the receiver will get the same data either way.  All you need to do is define the format of the message packets.

 

TCP data arrives as a stream with the operating system buffering it until you read it, so the reading end never knows nor cares how many write operations it took to send that data.  The receiving end simply needs to know how to interpret the data it reads.

Message 8 of 8
(4,343 Views)