Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #3744
| Path | csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!news.albasani.net!feeder.news-service.com!postnews.google.com!j35g2000prb.googlegroups.com!not-for-mail |
|---|---|
| From | Jean-Paul Calderone <calderone.jeanpaul@gmail.com> |
| Newsgroups | comp.lang.python |
| Subject | Re: Why doesn't this asyncore.dispatcher.handle_read() get called? |
| Date | Wed, 20 Apr 2011 13:01:08 -0700 (PDT) |
| Organization | http://groups.google.com |
| Lines | 116 |
| Message-ID | <1ef2274c-7b8a-4e93-bbbc-d791df0e93da@j35g2000prb.googlegroups.com> (permalink) |
| References | <11c683ce-3687-4a07-9d59-0371ba84562e@e8g2000vbz.googlegroups.com> |
| NNTP-Posting-Host | 66.31.201.117 |
| Mime-Version | 1.0 |
| Content-Type | text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding | quoted-printable |
| X-Trace | posting.google.com 1303329669 32394 127.0.0.1 (20 Apr 2011 20:01:09 GMT) |
| X-Complaints-To | groups-abuse@google.com |
| NNTP-Posting-Date | Wed, 20 Apr 2011 20:01:09 +0000 (UTC) |
| Complaints-To | groups-abuse@google.com |
| Injection-Info | j35g2000prb.googlegroups.com; posting-host=66.31.201.117; posting-account=vglGDQoAAABmaDKgNY6lPt_hwJvC5hhE |
| User-Agent | G2/1.0 |
| X-HTTP-UserAgent | Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16,gzip(gfe) |
| Xref | x330-a1.tempe.blueboxinc.net comp.lang.python:3744 |
Show key headers only | View raw
On Apr 20, 12:25 pm, Dun Peal <dunpea...@gmail.com> wrote:
> Hi,
>
> I'm writing and testing an asyncore-based server. Unfortunately, it
> doesn't seem to work. The code below is based on the official docs and
> examples, and starts a listening and sending dispatcher, where the
> sending dispatcher connects and sends a message to the listener - yet
> Handler.handle_read() never gets called, and I'm not sure why. Any
> ideas?
>
> Thanks, D.
>
> import asyncore, socket, sys
>
> COMM_PORT = 9345
>
> class Handler(asyncore.dispatcher):
> def handle_read(self):
> print 'This never prints'
>
> class Listener(asyncore.dispatcher):
> def __init__(self, port=COMM_PORT):
> asyncore.dispatcher.__init__(self)
> self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
> self.set_reuse_addr()
> self.bind(('', port))
> self.listen(5)
>
> def handle_accept(self):
> client, addr = self.accept()
> print 'This prints.'
> return Handler(client)
>
> class Sender(asyncore.dispatcher):
> def __init__(self, host):
> asyncore.dispatcher.__init__(self)
> self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
> self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
> self.connect( (host, COMM_PORT) )
> self.buffer = 'Msg\r\n'
>
> def handle_connect(self):
> pass
>
> def writable(self):
> return len(self.buffer) > 0
>
> def handle_write(self):
> sent = self.send(self.buffer)
> self.buffer = self.buffer[sent:]
>
> def test_communication():
> from multiprocessing import Process
> def listener():
> l = Listener()
> asyncore.loop(timeout=10, count=1)
> lis = Process(target=listener)
> lis.start()
> def sender():
> s = Sender('localhost')
> asyncore.loop(timeout=10, count=1)
> sen = Process(target=sender)
> sen.start()
> lis.join()
>
> test_communication()
You didn't let the program run long enough for the later events to
happen. loop(count=1) basically means one I/O event will be processed
- in the case of your example, that's an accept(). Then asyncore is
done and it never gets to your custom handle_read.
So you can try passing a higher count to loop, or you can add your own
loop around the loop call. Or you can switch to Twisted which
actually makes testing a lot easier than this - no need to spawn
multiple processes or call accept or recv yourself. Here's a somewhat
equivalent Twisted-based version of your program:
from twisted.internet.protocol import ServerFactory, Protocol
from twisted.internet import reactor
factory = ServerFactory()
factory.protocol = Protocol
reactor.listenTCP(0, factory)
reactor.run()
It's hard to write the equivalent unit test, because the test you
wrote for the asyncore-based version is testing lots of low level
details which, as you can see, don't actually appear in the Twisted-
based version because Twisted does them for you already. However,
once you get past all that low-level stuff and get to the part where
you actually implement some of your application logic, you might have
tests for your protocol implementation that look something like this:
from twisted.trial.unittest import TestCase
from twisted.test.proto_helpers import StringTransport
from yourapp import Handler # Or a better name
class HandlerTests(TestCase):
def test_someMessage(self):
"""
When the "X" message is received, the "Y" response is sent
back.
"""
transport = StringTransport()
protocol = Handler()
protocol.makeConnection(transport)
protocol.dataReceived("X")
self.assertEqual(transport.value(), "Y")
Hope this helps,
Jean-Paul
Back to comp.lang.python | Previous | Next — Previous in thread | Next in thread | Find similar
Why doesn't this asyncore.dispatcher.handle_read() get called? Dun Peal <dunpealer@gmail.com> - 2011-04-20 09:25 -0700
Re: Why doesn't this asyncore.dispatcher.handle_read() get called? Jean-Paul Calderone <calderone.jeanpaul@gmail.com> - 2011-04-20 13:01 -0700
Re: Why doesn't this asyncore.dispatcher.handle_read() get called? Dun Peal <dunpealer@gmail.com> - 2011-04-20 14:17 -0700
csiph-web