Note that there are some explanatory texts on larger screens.

plurals
  1. POVery simple python client/server working, but strange delays
    text
    copied!<p>I am trying to learn how to use sockets and a useful asynchronous backend. I've started in python with asyncore. After reading various online posts I've written a very simple chat server and connection client, reproduced below.</p> <p>It seems to work. I open a python interactive session and type</p> <pre><code>&gt; import chatserver &gt; server = chatserver.EchoServer('localhost', 7667) &gt; server.serve() </code></pre> <p>Then I open another IPython interactive session and type</p> <pre><code>&gt; import chatserver &gt; cxn = chatserver.Connection() &gt; cxn._connect('localhost', 7667) </code></pre> <p>When I do that, I get a log output in the server window indicating that a connection has been made. Good. Then I type</p> <pre><code>&gt; cxn.say('hi') </code></pre> <p>Nothing happens for a while, and then log messages show up for the server and client as expected.</p> <ol> <li>Why is this delay ocurring?</li> <li>Am I using the log functionality correctly?</li> <li>I used threading to make it so that I could use the interactive session while the asyncore loop does it's thing for the Connection. Did I do this in a reasonable way?</li> <li>(optional) If I don't include the line <code>self.out_buffer=""</code> in the Connection._connect function I get an error saying that .out_buffer does not exist. What's up with this?</li> </ol> <pre class="lang-python prettyprint-override"><code>import asyncore import socket import logging import threading logging.basicConfig(level=logging.DEBUG, format="%(created)-15s %(msecs)d %(levelname)8s %(thread)d %(name)s %(message)s") log = logging.getLogger(__name__) class Connection(asyncore.dispatcher_with_send): def __init__(self): asyncore.dispatcher.__init__(self) def _connect(self, host, port, timeout=5, password=None): self.host = host self.port = port self.out_buffer="" self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, port)) #Run the asyncore loop in its own thread so that we can use the interactive session self.loop = threading.Thread(target=asyncore.loop) self.loop.daemon = True self.loop.start() def say(self, msg): self.out_buffer = msg def handle_read(self): data = self.recv(4096) log.debug('Received %s'%data) class EchoHandler(asyncore.dispatcher_with_send): def handle_read(self): log.debug("handle_read") data = self.recv(1024) log.debug("after recv") if data: log.debug("got data: %s"%data) self.out_buffer = data else: log.debug("got null data") class EchoServer(asyncore.dispatcher): SOCKET_TYPE = socket.SOCK_STREAM ADDRESS_FAMILY = socket.AF_INET def __init__(self, host, port): self.address = (host,port) asyncore.dispatcher.__init__(self) self.create_socket(self.ADDRESS_FAMILY, self.SOCKET_TYPE) log.debug("bind address=%s %s"%(host,port)) self.bind(self.address) self.listen(1) def fileno(self): return self.socket.fileno() def serve(self): asyncore.loop() #Start asyncore loop in new thread # self.loop = threading.Thread(target=asyncore.loop) # self.loop.daemon = True # self.loop.start() def handle_accept(self): """Deal with a newly accepted client""" (connSock, clientAddress) = self.accept() log.info("conn made: clientAddress=%s %s"%(clientAddress[0], clientAddress[1])) #Make a handler for this connection EchoHandler(connSock) def handle_close(self): self.close() </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload