04-05-2025 10:44 AM
Hi,
I have read the documentation about the TCP Write function in LabView: https://www.ni.com/docs/en-US/bundle/labview-api-ref/page/functions/tcp-write.html
Do I have the guarantee that after the TCP Write function finished executing and no error occurs, the function has sent the exact number of bytes defined in the "data in" input?
Solved! Go to Solution.
04-05-2025 12:10 PM
The principles of dataflow dictates that a function cannot return outputs until it completes.
Are you trying to solve any particular problem? How much data are you going to send?
04-05-2025 12:31 PM
The principles of dataflow dictates that a function cannot return outputs until it completes.
The question comes from my use case. I have a working implementation of a TCP communication between a server instance running on LabView, and a client running a C executable using the sys/socket.h library.
The C library does not guarantee that after the system call "send" (the C equivalent of TCP write) the whole data buffer is sent to the receiver. This is easily solved by repeatedly calling the "send" function until all expected bytes are sent.
So, my question is: could it happen that after a TCP write in LabView not all the expected bytes (defined in "data in") are sent?
I'm sending around 150 bytes at a 50 Hz frequency. I know it would be very unlikely but I need the certainty that it can't happen.
04-05-2025 02:17 PM - edited 04-05-2025 02:21 PM
Do I have the guarantee that after the TCP Write function finished executing and no error occurs, the function has sent the exact number of bytes defined in the "data in" input?
No you don't have that guarantee! When the TCP Write function returns without error, that only means that LabVIEW was successful in passing the data to the underlying socket library. It also means that the socket library still thinks that the socket is alive and connected and that it will be able to send the data eventually to the connected remote point. If that believe is right or wrong is another story.
But what you mention in your second post is a different story. When the function returns it means that yes, LabVIEW was successful to transfer the entire buffer to the socket library, calling send() multiple times if necessary. So you don't have to do a Write retry with part of the unsent buffer as you do in C. LabVIEW abstracts that away for you. TCP Write either returns without error after having transferred all the data to the socket library or it returns an error. There is nothing in between.
04-05-2025 03:50 PM
But what you mention in your second post is a different story. When the function returns it means that yes, LabVIEW was successful to transfer the entire buffer to the socket library, calling send() multiple times if necessary. So you don't have to do a Write retry with part of the unsent buffer as you do in C. LabVIEW abstracts that away for you. TCP Write either returns without error after having transferred all the data to the socket library or it returns an error. There is nothing in between.
Amazing, that is what I needed to know!
04-06-2025 10:02 AM - edited 04-06-2025 10:03 AM
@rolfk wrote:
TCP Write either returns without error after having transferred all the data to the socket library or it returns an error. There is nothing in between.
I actually wasn't sure what needs to happen before the function returns. For example if the remote system goes down, you would eventually get a timeout error.
Imagine the following scenario: Writing a 10MB data string at once (there is no hard upper size limit!) The socket library need to send it in many packets, some might arrive in duplicate, some out of order, some might get fragmented in transit, and some might get lost and need to be retransmitted. All this is handled transparently by the TCP protocol. You would think that the function should only return after the last ACK has been received back. Before that, we cannot tell if a connection based transfer has succeeded.
(In any case, I agree that re-sending the same data would not make any sense)
04-06-2025 10:44 AM
@altenbach wrote:
@rolfk wrote:
TCP Write either returns without error after having transferred all the data to the socket library or it returns an error. There is nothing in between.
I actually wasn't sure what needs to happen before the function returns. For example if the remote system goes down, you would eventually get a timeout error.
Imagine the following scenario: Writing a 10MB data string at once (there is no hard upper size limit!) The socket library need to send it in many packets, some might arrive in duplicate, some out of order, some might get fragmented in transit, and some might get lost and need to be retransmitted. All this is handled transparently by the TCP protocol. You would think that the function should only return after the last ACK has been received back. Before that, we cannot tell if a connection based transfer has succeeded.
(In any case, I agree that re-sending the same data would not make any sense)
That is not how the Berkeley socket library works, which incidentally is also what Microsoft used to implement Winsock, although they did eventually add Windows specific extensions for asynchronous operations. For LabVIEW these asynchronous functions are not really used and that makes the TCP/IP and UDP code underneath the LabVIEW nodes almost platform independent.
Basically the actual socket function send() for connected sockets (aka TCP) and sendto() for unconnected sockets (aka UDP) simply return with an indication of the actually consumed bytes of the buffer or an error indication. The emphasis here is on consumed bytes. The socket library only guarantees that it has copied that many bytes into a socket specific buffer to be sent out eventually, not that the data has actually been sent out on the wire and certainly not that the remote side has acknowledged it yet. If the function does not return an error indication it is the callers responsibility to verify that the number of consumed bytes matches the number in the passed in buffer. If it is less than that (but it can't really be ever more than that) it is the applications responsibility to attempt to call send() again with the remainder.
As soon as the socket library detects that something went wrong, such as an actual FIN indication from the remote side indicating the socket was shutdown there, or a number of resends for a packet that exceeds an internal threshold, or a certain number of unacknowledged packets, or a timeout, etc, the socket status is set accordingly and any subsequent call of any function on that socket will return an according error. So the send() call for a particular buffer never will immediately return an error, unless the socket has been terminated by the remote side already, or previous activity on that socket has eventually caused an error.
Yes this makes even the connection based TCP protocol asynchronous. There is no simple way to detect that a connection failed after the initial connection handshake other than trying to do actual data transfers and see the reaction on that. If TCP would require to wait on an ack of all packets that make up a write buffer, the protocol would be totally unsuited to implement any high speed command response operation!
04-06-2025 11:14 AM - edited 04-06-2025 11:21 AM
Thanks. So exactly what step can generate a timeout error for the TCP write function? (default is 25s, and I assume that the function can stall up to 25 seconds before returning).
From the help:
timeout ms specifies the time, in milliseconds, for the function to write bytes to a device before the function completes and returns an error. The default value is 25,000 ms. A value of –1 indicates to wait indefinitely.
I guess the term "device" is a bit vague. 😄