I have an issue regarding TCP communication in LabVIEW I would like to ask help with. I have two applications which communicate over TCP with each other. Both applications try to connect to each other, until they manage to establish connection. Client application is afterwards sending data to the server. Communication works fine most of the time. However, when I close connection on server side, I get an unexpected behaviour.
I close connection on server side and stop reading TCP data. On client side, application throws error 56. This is fine. But then client tries to establish connection once again. Despite the server side is idling, it somehow manages to establish connection and starts to send data once again, although there is apparently no one reading it. When I try to re-establish connection from the server, I create listener again and after this is successful, start reading data again. Now, I get all the data that client sent during the period when server wasn´t listening.
My question is - is this behaviour normal? Should not be client unable to open connection to the server after server closes connection and manage to establish it again only after server starts listening?
Actually when you shutdown a socket (which is the underlaying resource managing the listener as well as a connection) this socket is not immediately destroyed in the socket library. There may be some low level socket option that can be set to influence that but it is not something usually done. The socket goes through a CLOSE_WAIT and LAST_ACK state for a passive close (when the remote side disconnects) and an FIN_WAIT_1, FIN_WAIT_2 and TIME_WAIT state for an active close (when the local side decides to close the connection).
These wait states typically take up one to several minutes in which the socket still receives packets and acknowledges them accordingly. And while I have not seen this myself so far it seems that reopening a listen socket in your server simply attaches to the according socket driver queue again.
Do you use the simple TCP Listen.vi or rather the seperate TCP Create Listener and TCP Wait on Listener nodes? Because the first also has a so called Internezine avoider inside which may be part of what you are seeing. Without that trying to shutdown a Listener and then trying to reopen it again immediately would always fail since the underlaying socket would still be active and the socket library would refuse to create a new listen socket for the same local port number, since there is already (still) another socket open on that port until it has cycled through all the WAIT states. But this socket remaining in an unclosed state for some time is entirely out of the hands of LabVIEW. The Internezine Avoider is a workaround to avoid running into errors when trying to quickly close and reopen listeners in a loop but could have this seemingly weird side effect.
The proper means to deal with TCP Servers in LabVIEW is to explicitedly use the TCP Create Listener and TCP Wait on Listener seperately. It's more work and makes creating a TCP server more challenging but it's the way the Berkeley socket implementation (that Windows simply copied from Unix) is meant to be used.