Closing Connections
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 the connection closing automatically, without any help from your Tibbo BASIC/C program or the VM. In fact, the socket will accept a 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_event event 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 the 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."
A 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.
Note 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 sock.reset, it may sometimes result in a discard. For more information read sock.close, sock.reset, and sock.discard.
Actively Closing UDP Connections
For UDP, no matter what method you use to close the "connection," the result will still be as if 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.
Don't 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, or sock.discard methods, 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 explains how to find out the actual connection status at any time (see the sock.state and sock.statesimple read-only properties).
The asynchronous nature of the sock. object has some interesting implications. The 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). 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 of this in More On the Socket's Asynchronous Nature.
Connection Timeouts
The sock.connectiontout property 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).
The sock.toutcounter read-only property informs your application of the time passed since the data was last exchanged across the connection. Each time there is some data sent or received, sock.toutcounter is reset to zero. The property increments at 0.5-second intervals while no data is moving through this socket.
If sock.connectiontout is not at 0, sock.toutcounter increments until it reaches the value of sock.connectiontout and the connection is terminated. The sock.toutcounter property then stays at the value of sock.connectiontout.
If sock.connectiontout is at 0, the maximum value that sock.toutcounter can reach is 1. That is, sock.toutcounter will be at 0 after the data exchange and at 1 if at least 0.5 seconds have passed since the last data exchange.
Normally, 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 in which the socket is running in the TCP-HTTP mode.
In Accepting Incoming Connections, we explained that the socket automatically switches into the HTTP mode if a TCP connection is accepted on one of the ports from sock.httpportlist. 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., an 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. In fact, when the socket is in the HTTP mode, your sock.close, sock.reset, and sock.discard invocations will simply be ignored. There is a sock.httpnoclose property that alters the standard socket behavior in the HTTP mode. Set this property to 1 — YES and the connection will be kept opened even after the socket has sent all of the HTTP reply out.
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.