How to implement non blocking socket server in python

18,118

Have a look to Asyncore, it is exactly done for what you're searching for :)

http://docs.python.org/2/library/asyncore.html

Cheers,

K.

Share:
18,118
Zac
Author by

Zac

Updated on June 04, 2022

Comments

  • Zac
    Zac almost 2 years

    A similar but different question:

    I have an IRC client that generates strings. This IRC client uses a hook to call a method (somone_said) whenever someone says something. I want to send this string over a socket to my flash client.

    I have a working client in flash and a server in python but the problem is that it blocks: 1) while listening for the client connection 2) while waiting for the next message to be generated

    This stops the IRC client from responding to other inputs.

    I think I need to create my socket in a separate thread but this creates three more problems. 1) how does my someone_said event driven method access the socket 2) What if someone says something when there is no server client connection (while listening) or if the client has closed the connection. 3) How to check if the thread is alive and if not to open a new one?

    My blocking server code is this:

    # Echo server program
    import socket
    import sys
    
    HOST = None               # Symbolic name meaning all available interfaces
    PORT = 7001              # Arbitrary non-privileged port
    s = None
    
    def startListening():
        print "starting to listen"
    
        for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
                                      socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
            af, socktype, proto, canonname, sa = res
            try:
                s = socket.socket(af, socktype, proto)
            except socket.error as msg:
                s = None
                continue
            try:
                s.bind(sa)
                s.listen(1)
            except socket.error as msg:
                s.close()
                s = None
                continue
            break
        if s is None:
            print 'could not open socket'
            sys.exit(1)
        conn, addr = s.accept()
        print 'Connected by', addr
        while 1:
            try: 
                data = conn.recv(1024)
            except:
                print "cannot recieve data"
                break
            if not data: 
                break
            print data
            message = ""
            while not "quit" in message:
                message = raw_input('Say Something : ') # This will come from event driven method
                try: 
                    conn.sendall(message)
                except Exception as exc:
                    print "message could not be sent"
                    break
    
    
        conn.close()
        print "connection closed"
    
    while 1:
        startListening()
    

    The xchat module python script works like this (requires HexChat to run)

    __module_name__ = "Forward Module"
    __module_version__ = "1.0.0"
    __module_description__ = "Forward To Flash Module by Xcom"
    
    import sys
    import xchat
    
    def someone_said(word, word_eol, userdata):
        # method called whenever someone speaks in IRC channel
        username = str(word[0]) # From IRC contains the username string
        message = str(word[1]) # From IRC contains the user message
        sendString = username + " : " + message
        send_to_server(sendString)
    
    
    def send_to_server(message):
        # send over socket method to be implemented here
    
    xchat.hook_print('Channel Message' , someone_said)
    

    I've been banging my head against this wall for days now. Help me obi wan kenobi, you're my only hope.

  • Zac
    Zac almost 11 years
    I added some asyncore code, but the script still blocks while waiting for connection and between sends. This is unacceptable because the HexChat IRC client has to do other things while this is going on.
  • Koreth
    Koreth almost 11 years
    Python provides you the ability to use socket.setblocking(0) , after which your socket will be non-blocking. The main documentation is avalaible here (docs.python.org/2/howto/sockets.html#non-blocking-sockets) and you also have some utilization here (pymotw.com/2/select/index.html).
  • Zac
    Zac almost 11 years
    The program still hangs while listening for the client to connect or between sends. I can't allow the program to hang/pause like that because it is supposed to be doing other things at the same time.