More On the Socket's Asynchronous Nature
|Top Previous Next|
In Establishing Outgoing Connections and Closing Connections topics we have already touched on the subject of the sock object's asynchronous nature. This topic offers further details on what that means for your application.
Executing sock.connect, sock.close, sock.reset, or sock.discard method does not mean that your connection gets established or terminated by the time your program reaches the next statement. Executing these statements merely instructs the Master Process what to do with the connection. Connection establishment/termination can take some time and your application doesn't have to wait for that to complete. Checking Connection Status topic explained how to find out actual connection status at any time (see sock.state and sock.statesimple read-only properties).
There are certain situations when your program has to take the above into account. Here is one example. Supposing, we want to know the MAC address of a remote device to which we are establishing an outgoing connection. Naturally, we can do it this way:
The above is a good example of event-driven programming. Sometimes, however, you need to establish a connection and "follow-up" on it in the same event handler. So, how do we do this? Here is a simple, and WRONG code:
And here is the correct way to handle this. For clarity, this example assumes that connection will definitely be established.
Here is even more interesting example. Supposing, you want to close and reestablish a TCP connection right within the same event handler. Here is a wrong way of doing this:
You see, executing sock.close doesn't really close the connection — it only issues the instruction (to the Master Process) to close the connection. So, by the time program execution gets to the sock.connect method your previous connection is still on!
Correct way is to wait for the connection to actually be closed before executing sock.connect. Here is another example — not quite correct either — but closer to the truth.
OK, this is better. One final correction and the code is complete. In the Closing Connections topic ("Socket re-use after connection closing" section) we have already explained that the OS makes sure that the on_sock_event has a chance to execute after the old connection is closed and before the new one is established. In the above example both sock.close and sock.connect are in the same event handler — the on_sock_event won't squeeze in between them unless you use the doevents statement! Here is the correct code:
Notice how doevents is placed after the while-wend loop. It is absolutely essential that you do it this way! Of course, now that you have at least one doevents in the event handler you might as well add doevents in all "places of waiting" — just to let other events execute sooner.