I have a PLC program using a TCPServer to connect to a client running on a PC. The connection is fine when the PLC program has restarted. However, after a series of disconnection and reconnections, it seems to client can no longer establish connection to the PLC program. Upon checking the TcpServer status, the status seems to be busy.
A workaround is to restart the PLC program which enables the connection to be re-established.
I was wondering if there is a way to refresh the TcpServer object to be in the same state as when the program has just restarted?
if the server is busy and has no errors it should be fine, shouldn’t it?
What is the error the client is showing?
The only thing that comes to mind are handles… the AR has limited handles for most of the things like file handling, port opening etc. so make sure to give them back
maybe you ran into a so called TCP half-open connection.
This is a TCP protocol based topic: it means more ore less, that one side of the TCP channel is inconsistent to the other side (in “TCP protocol language” - the sequence and acknowledge counters of both communication partners are not longer aligned).
A half-open connection mostly happens because of a non-standard TCP channel shutdown from one partner, for example because of a power-off / spontanous reboot, a cable link loss, or other reasons.
Normally, a standard TCP channel shutdown is communicated by both partners by sending and acknowledging a TCP packet with FIN bit set (that’s done by the driver). From the PLC point of view, this is done by calling the TcpClose() function block.
So, if one partner does not send / get this FIN package, under some circumstances the other partner does not know that the channel should be closed.
There’s no easy way to detect a half-open connection - so I recommend always to:
do sending and receiving of data on both ends of the channel, so on server and client side
sending AND receiving on the socket will give you some more error information to interprete, bacause some errors are only delivered by the TcpSend(), others only by TcpRecv()
Implement on both sides a send & receive timeout, and send every X seconds a “lifesign data packet”, even if there’s no data needed to transfer
if this is not possible for any reason, define a server sided timeout, and close and re-open the server after this period when no data or connection was received → for example webservers do that more or less in the same way.
After getting no data for a time > timeout (means: no longer receiving a lifesign), execute a TcpClose() on server and on client side
execute a TcpOpen() on both sides after the TcpClose() has finished → latest after your lifesign timeout, both partners have closed and re-opened the TCP channel, and the channel itself will be consistent again!
Don’t forget to interprete TcpRecv().status = 0 AND tcpRecv().recvlen = 0 as a remote close
Receiving a packet (.status = 0) with a datasize of 0 (.recvlen = 0) means, that the remote partner has sent a FIN packet!
the only right reaction on receiving a FIN packet is doing a TcpClose() also on the local side.