[Tutor] Re: asyncore, asynchat, sockets, and threads

Michael Welsh mwelsh@abwatley.com
Wed Jul 16 09:02:01 2003


On Tuesday 15 July 2003 09:58 pm, Lee Harr wrote:
>
> I think your intuition about using a Queue may be the
> right thing in the gui client to you chat server.
>
> Basically, you would have 2 threads:
>
> Network client thread feeds messages in to queue.
> Gui thread reads messages from queue and displays them.
>

I may still turn to Queues but I got the basic plumbing working without them 
late last night.  Reading the aysncore.py / asynchat.py source and the 
following documentation helped:

Medusa  http://www.nightmare.com/medusa/programming.html
PythonDev http://www.python.org/dev/doc/devel/lib/module-asynchat.html

I also have a few Python books that do their best to explain these concepts.  
I'll admit, programming asyn socket communication is not trivial the first 
time you do it.  But that is true of most things. <grin>

Here's what I've learned so far on the client side...maybe it will help 
somebody who is just discovering asyn.

The main app inits a frame which inits a Thread and a ListCtrl among others.  
I then build the rest of the GUI including a function to recieve a 'custom 
network event'.  This simple function calls my 'list.add' function of the 
ListCtrl.  The custom network event is a separate class.  

The Thread creates a socket.socket, connects it (to the pre-defined constants 
- my server app on a different machine),  and hands the socket off to an 
instance of asyn_chat.  Discovering that you hand a live socket to aysn_chat 
was my first "AH-HA" moment.  It kinda 'clicked' that the asyncore/asynchat 
collection is just a bunch of functions that help you work the live wire.

Also included with the hand-off is a handler function that gets fired when the 
async_chat.collect_incoming_data gets fired.  The handler function belongs to 
the Thread and only does one thing: call the custom network event... all the 
while passing the data from the socket as it goes.  

After socket creation, connection, and hand-off, the Thread then calls an 
instance of a custom event loop class containing an asyncore.loop.  It took 
me a little while to figure out that it is OK to call the aysncore.loop on an 
asyn_chat object without a dispatcher.   In all the samples, newsgroup 
threads, etc that I read; they all created an aysn_chat FROM the 
asyncore.dispatcher on listen().  AH-HA number two... you don't need a 
disptcher because asyn_chat IS a dispatcher (read the source).  

One of the great things about Python (and wxPython in my case) is that all 
this is tested and works on NT and Linux.  I haven't tried to package it for 
distribution.  So, to summarize:

On App Launch
frame > thread, list
thread > socket > asyn_chat > loop

On User Input
send data to thread.socket (asyn_chat).push
..goes to server, server echos to all

On All Clients
asyn_chat colletcts > calls handler function (thread)
thread fires network event
GUI recieves event > calls list.add

My next steps are to have the server log all messages to a database.  I also 
want to add authentication.  Maybe even the abiltiy to choose from several 
'channels' before socket creation.  If I can make it modular enough, I may be 
able to 'plug in' comm abilities to other apps.  Hmmm, streaming data over 
the wire... Hey, asyn socket communication can really be fun!

Michael