Understanding TCP Reconnects
|Top Previous Next|
The sock object has a unique feature- support for "reconnects". To simplify the explanation, let us start from a description of a real-life problem first.
When reconnects save the day
Supposing, you have a host on the network that is engaged in a TCP connection with one of the sockets of the socket object. The data is sent across this connection from the host to our socket. For a while, everything is fine and then the host momentarily loses power and reboots. Our socket doesn't know anything about this- from its point of view, the TCP connection is still OK. Just because no data is arriving from the host does not mean that there is a problem!
Meanwhile, the host reboots and attempts to establish a new connection to the socket- and gets rejected! This is because the socket thinks it is already engaged in a TCP connection- the one that has been left hanging since the host went down! This stagnant connection will remain in place until it times out- if timeouts are enabled at all through the sock.connectiontout property.
Reconnects are a nifty way out of this situation. You enable reconnects through the sock.reconmode (reconnection mode) property. For the above example, you typically set the sock.reconmode= 2- PL_SOCK_RECONMODE_2. This mode means, that if the socket is already engaged in a connection, and then there is an incoming connection attempt that originated from the same host (and any port), then the socket will forget everything about the original connection and accept the new one.
For our example case, this is the solution- after rebooting the host tries to establish a new connection to our socket. The socket then "realizes" that this new connection is being attempted from the same host as the connection already in progress, discards the original connection and accepts the new one!
Reconnects must target the same port and interface!
Even when the socket has more than one listening port (i.e. sock.localportlist= "1000,1001") the reconnect will only be accepted if it targets the same local port of the socket as the one already engaged in the current connection being "replaced". In other words, to be successful, the reconnect must target the port that is currently returned by the sock.localport read-only property.
The interface must also be the same. The host can't make an original connection through Ethernet, and then reconnect through Wi-Fi.
Which mode to choose?
As you can see, the sock.reconmode property gives you several "strictness levels" of dealing with reconnects. Which one to choose? Let us explain why the choice of sock.reconmode= 2- PL_SOCK_RECONMODE_2 is the most common. Typically, when the host is establishing an outgoing connection it does so from the ever changing port number. Basically, there is a "pool" of ports for this purpose and each new connection the host needs to establish will be made from the next port in the pool.
Each time the host connects to our socket the port on the host could be different. This is why it makes sense to accept reconnects from the same IP but any port. Disadvantage? Any connection originating from this host will essentially be treated as the same and the only connection!
Some programs (few!) establish connections from a specific, preset port. This may be done for a variety of reasons- no time to go into this here- just let us say, sometimes this is the case. If you are dealing with such a case then you can safely set sock.reconmode= 1- PL_SOCK_RECONMODE_1. This way, reconnects will only be accepted from the same IP and the same port as the original connection.
Total promiscuity — mode 3!
Finally, there is a mode (3- PL_SOCK_RECONMODE_3) when the socket will accept a reconnect from any host or port. Basically, this means, that whatever connection is in progress, it will be interrupted and replaced by any other incoming connection.
Do not use reconnects for HTTP sockets!
Reconnects and HTTP do not play nicely together. When you request an HTML page, several simultaneous HTTP requests may be generated (one for the page itself, several — for pictures on this page, etc.). All these requests will use a separate TCP socket, so multiple sockets will be opened (almost) at the same time. Now, what will happen if even just one of your application's "HTML" sockets has reconnects enabled? This single socket will intercept all HTML requests. So, if loading the HTML page needed 3 separate requests and TCP sessions, this socket will get them all — and each next session opening will discard the previous one. Result won't be pretty!