Thread's, async_chat and asyncore

Jos hyakugei at gmail.com
Mon Oct 3 22:14:40 EDT 2005


Hello.

I'm using the asyncore and _chat modules to create a network server. I
also have, running in a separate thread(s), a "producer" which needs to
"push" data onto the network connection(s). (This is all for a
multi-player game server, so the threads would be individual games,
that need to update the players when new events happen in the game)

I currently have a module level list of async_chat instances, which the
thread then reads and uses the 'push' method of async_chat.

I've done some very quick tests, but wanted to know more formally if
the async_chat.push() method is thread safe?

ie. can i be sure that the data that the thread pushes onto the
connection will always be complete, and never "over-written" by another
thread?

Here is an example, which creates a whack of threads, which push their
message down the first connection made to the server. I just use a
telnet client to test it. I haven't seen any over-writing of values,
but this is a very basic test/example of what i'm doing. I just want to
make sure that this _is_ ok, or if i should be using a Queue...

<file>
import asynchat
import asyncore
import socket
from threading import Thread
import time
import random

clients = []

class pulse_thread(Thread):
    def __init__(self, string):
        Thread.__init__(self)
        self.msg = string

    def run(self):
        while True:
            time.sleep(random.random())
            if(len(clients)):
                clients[0].push(self.msg)

class Chat(asynchat.async_chat):

    def __init__(self, sock, addr, terminator="\r\n", name="me"):

        asynchat.async_chat.__init__(self, conn=sock)

        self.rmq = []
        self.terminator = terminator
        self.set_terminator(self.terminator)
    # push self onto module client list, so threads can access me
        clients.append(self)

    def collect_incoming_data(self, data):
        """Buffer the data"""
        self.rmq.append(data)

    def found_terminator(self):
        print "".join(self.rmq)
        self.rmq = []

class cServer(asyncore.dispatcher):

    # constructor method
    def __init__(self, addr, terminator="\r\n"):

        # initalize asyncore
        asyncore.dispatcher.__init__(self)

        self.terminator = terminator

        # create a socket to listen on
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)

        # bind the socket to the ip/port
        self.bind(addr)

        # listen ??? don't know about the 5 ????
        self.listen(50)

    # EVENT handle_accept - fired when server accepts an new connection
    def handle_accept (self):
        # fire the accept method > returns a connection object
        conn, addr = self.accept()

        # extend the connection with cSock Class (another asyncore)
        #cSock(conn, addr)
        Chat(conn,addr,self.terminator)


if __name__ == '__main__':

    for i in range(1,99):
        x = pulse_thread(":%02d:\n\r" % (i,))
        x.start()

    myserver = cServer(('127.0.0.1',7000))

    asyncore.loop()
</file>

Please let me know if this is totally the _wrong_ way to do it!

Thanks,
Jos




More information about the Python-list mailing list