[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