|
Closing Connections |
Top Previous Next |
Passive TCP connection termination
When your socket is engaged in a TCP connection with another host on the network, this host may choose to terminate the connection. This can be done through a "graceful disconnect" sequence ("FIN-ACK-FIN-ACK") or through a reset ("RST" packet).
In both cases the socket will handle connection closing automatically, without any help from your BASIC program or the VM. In fact, the socket will accept connection termination even when the VM is stopped (for example, it was paused on your breakpoint). All communications are handled by the master process, so the socket does not need the VM to terminate the connection.
There is one intricate detail in the connection termination process that you will have to understand clearly. When the VM is not running, the socket can accept an incoming connection (active open) and can accept an active close. However, the socket won't be able to accept another (next) incoming connection until the VM has had a chance to run and execute the on_sock_eventevent handler (see Checking Connection Status).
Here is why. In many cases there is a need to perform certain actions (like, maybe, clear some buffers, initialize variables, etc.) after the previous connection ends and before the new one begins. Not letting the socket accept next connection before your program has a chance to respond to connection termination is a way to achieve this!
Actively closing TCP connections
A TCP connection can be closed, reset (aborted), or discarded using three different methods- sock.close, sock.reset, and sock.discard.
The recommended (and polite!) way of closing a TCP connection is through the sock.close method. This will initiate a proper closing sequence ("FIN-ACK-FIN-ACK"), known as a "graceful disconnect".
Connection reset is slightly more "rude"- your socket will simply tell the other end that "it is all over" (by sending the "RST" packet).
Finally, the sock.discard method simply makes your socket forget about the connection- the other side is not notified at all.
Just like with connection establishment, you can monitor the progress of connection termination- see Checking Connection Status.
|
Notice, that depending on the socket state at the moment of sock.close method invocation, the socket may need to resort to a simple connection closing option- reset or discard. Similarly, when you use the sock.reset, it may sometimes result in discard. For more information read the sock.close, sock.reset, and sock.discard topics. |
Actively closing UDP connections
For UDP, not matter what method you use to close the "connection", result will still be as if the sock.discard was invoked. This is because in reality there is no such thing as a proper UDP connection termination so simply "forgetting" about the connection is the only option the socket has.
Do not forget: connection handling is fully asynchronous!
Keep in mind that the sock object handles communications asynchronously. When the VM executes the sock.close (sock.reset, sock.discard) method it does not mean that the connection is done with by the time the VM gets to the next program statement. Executing these methods merely instructs the Master Process to terminate the connection. Connection termination can take some time and your application doesn't have to wait for that to complete. Checking Connection Status topic explains how to find out actual connection status at any time (see sock.state and sock.statesimple read-only properties).
|
Asynchronous nature of the sock object has some interesting implications. More On the Socket's Asynchronous Nature topic contains important information on the subject, so make sure you read it! |
Socket re-use after connection closing
When the socket connection terminates, the socket is ready to accept another incoming connection or establish a new outgoing connection (if so configured) -- with one little caveat! There is a special built-in mechanism that ensures that your application has a chance to react after the previous connection terminates and before the next one is established.
For example, you might need to clean some buffers before each new incoming TCP connection. Naturally, you want this to happen before the new connection is actually accepted.
Typically, your program achieves this by executing code placed in the on_sock_event event handler (this event is explained in Checking Connection Status topic). The socket will not be able to engage in the new connection until the on_sock_event has a chance to execute. There is an interesting example on this in the More On the Socket's Asynchronous Nature topic.
Connection timeouts
The sock.connectiontout provides a way to automatically terminate a connection across which no data was exchanged for a predefined period of time. For TCP, reset (abort) is used, while UDP "connections" are simply discarded.
Connection timeout is a useful way to exit "hanged" connections (this happens a lot with TCP on large networks).
Normally, TCP-HTTP connections close automatically
There is one case where your socket will perform an active graceful disconnect without you using the sock.close method. This is the case when the socket is running in the TCP-HTTP mode.
In Accepting Incoming Connections we have already explained that the socket automatically switches into the HTTP mode if a TCP connection is accepted on one of the ports from the sock.httpportlist list. The socket can also be switched into the HTTP mode programmatically, through the sock.httpmode property.
Default HTTP functionality requires that the TCP connection is closed once the HTTP server has finished sending out its "response" (i.e. HTML page or another file that has been requested). In this situation the socket won't need the sock.close from your program- the connection will be terminated automatically. This default functionality can be altered through the sock.httpnoclose property.
Just like in all other cases, a new connection on the socket won't be accepted until your program has had a chance to respond- this was explained above.