socket programming strategy
Richie Hindle
richie at entrian.com
Wed Jan 22 10:36:40 EST 2003
[Andrew Bennetts]
> An example of doing this in Twisted
[Richie]
> This is a wonderful example
...except for two bugs. 8-)
It falls over when you feed it lots of lines at once (eg. by telnetting
to it and pasting a bunch of lines into the terminal) for two reasons:
o It deletes completed jobs from the wrong end of the stack.
o The callback can be called with no work left, so it needs to check
that the stack isn't empty.
Here's a fixed version, with my edits marked with 'RJH':
----------------------------------------------------------------------
from twisted.protocols import basic
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
class LongMultiplicationProtocol(basic.LineReceiver):
"""A protocol for doing long multiplications.
It receives a list of numbers (seperated by whitespace) on a line, and
writes back the answer. The answer is calculated in chunks, so no one
calculation should block for long enough to matter.
"""
def connectionMade(self):
self.workQueue = []
def lineReceived(self, line):
try:
numbers = map(long, line.split())
except ValueError:
self.sendLine('Error.')
return
if len(numbers) <= 1:
self.sendLine('Error.')
return
self.workQueue.append(numbers)
reactor.callLater(0, self.calcChunk)
def calcChunk(self):
# RJH:
# Make sure there's some work left; when multiple lines are received
# while processing is going on, multiple calls to reactor.callLater()
# can happen between calls to calcChunk().
if self.workQueue:
# Get the first bit of work off the queue
work = self.workQueue[0]
# Do a chunk of work: [a, b, c, ...] -> [a*b, c, ...]
work[:2] = [work[0] * work[1]]
# If this piece of work now has only one element, send it.
if len(work) == 1:
self.sendLine(str(work[0]))
del self.workQueue[0] # RJH: Not `self.workQueue.pop()`!
# Schedule this function to do more work, if there's still work
# to be done.
if self.workQueue:
reactor.callLater(0, self.calcChunk)
class LongMultiplicationFactory(ServerFactory):
protocol = LongMultiplicationProtocol
if __name__ == '__main__':
from twisted.python import log
import sys
log.startLogging(sys.stdout)
reactor.listenTCP(1234, LongMultiplicationFactory())
reactor.run()
----------------------------------------------------------------------
I-know-it's-only-an-example-but-I-can't-help-myself-ly yrs,
--
Richie Hindle
richie at entrian.com
More information about the Python-list
mailing list