Advertisement
Guest User

twisted client

a guest
Aug 5th, 2012
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.79 KB | None | 0 0
  1. # This is the Twisted Get Poetry Now! client, version 2.0.
  2.  
  3. # NOTE: This should not be used as the basis for production code.
  4.  
  5. import datetime, optparse
  6.  
  7. from twisted.internet.protocol import Protocol, ClientFactory
  8.  
  9.  
  10. def parse_args():
  11.     usage = """usage: %prog [options] [hostname]:port ...
  12.  
  13. This is the Get Poetry Now! client, Twisted version 2.0.
  14. Run it like this:
  15.  
  16.  python get-poetry.py port1 port2 port3 ...
  17.  
  18. If you are in the base directory of the twisted-intro package,
  19. you could run it like this:
  20.  
  21.  python twisted-client-2/get-poetry.py 10001 10002 10003
  22.  
  23. to grab poetry from servers on ports 10001, 10002, and 10003.
  24.  
  25. Of course, there need to be servers listening on those ports
  26. for that to work.
  27. """
  28.  
  29.     parser = optparse.OptionParser(usage)
  30.  
  31.     _, addresses = parser.parse_args()
  32.  
  33.     if not addresses:
  34.         print parser.format_help()
  35.         parser.exit()
  36.  
  37.     def parse_address(addr):
  38.         if ':' not in addr:
  39.             host = '127.0.0.1'
  40.             port = addr
  41.         else:
  42.             host, port = addr.split(':', 1)
  43.  
  44.         if not port.isdigit():
  45.             parser.error('Ports must be integers.')
  46.  
  47.         return host, int(port)
  48.  
  49.     return map(parse_address, addresses)
  50.  
  51.  
  52. class PoetryProtocol(Protocol):
  53.  
  54.     poem = ''
  55.     task_num = 0
  56.     # called as soon as client read it by TCP (doRead())
  57.     def __init__(self, timeout_period = None):
  58.         object.__init__(self)
  59.         self.delayed_call = None
  60.         self.timeout_period = timeout_period or 20
  61.     def dataReceived(self, data):
  62.  
  63.         # import sys, traceback, os
  64.         # traceback.print_stack()
  65.         # os._exit(0)
  66.         self.poem += data
  67.         msg = 'Task %d: got %d bytes of poetry from %s'
  68.         print  msg % (self.task_num, len(data), self.transport.getPeer())
  69.  
  70.     # this callback called either if poem read is finished or
  71.     # task is timeout
  72.     # first case: connectionLost called by twisted.internet.tcp.py module in readConnectionLost callback:
  73.     # in posixbase : in _doReadOrWrite disconnects our client
  74.     def connectionLost(self, reason):
  75.         import sys, traceback, os
  76.         traceback.print_stack()
  77.         os._exit(0)
  78.  
  79.  
  80.         self.poemReceived(self.poem)
  81.         print reason
  82.  
  83.     def timeout_task(self):
  84.         print "%d task timed out" % self.task_num
  85.         self.transport.loseConnection()
  86.  
  87.     def connectionMade(self):
  88.         from twisted.internet import reactor
  89.         self.delayed_call = reactor.callLater(self.timeout_period,  self.timeout_task)
  90.    
  91.     def success(self):
  92.         if self.delayed_call is None: return
  93.         self.delayed_call.cancel()
  94.         print 'task sucecssfully finished!'
  95.      
  96.     def poemReceived(self, poem):
  97.         self.factory.poem_finished(self.task_num, poem)
  98.         self.success
  99.  
  100. class PoetryClientFactory(ClientFactory):
  101.  
  102.     task_num = 1
  103.  
  104.     protocol = PoetryProtocol # tell base class what proto to build
  105.  
  106.     def __init__(self, poetry_count):
  107.         self.poetry_count = poetry_count
  108.         self.poems = {} # task num -> poem
  109.        
  110.     # called if timeout
  111.     # def postpone_task(self, task_num = None, poem = None):
  112.     #     print "%d task has been posponed" %(task_num)
  113.     #     (task_num, poem)
  114.    
  115.     def buildProtocol(self, address):
  116.         # tries to connection protocol to transport by address
  117.         proto  = ClientFactory.buildProtocol(self, address)
  118.         proto.task_num = self.task_num
  119.         self.task_num += 1
  120.         # if something goes wrong call it later
  121.          
  122.         return proto
  123.    
  124.     def poem_finished(self, task_num=None, poem=None):
  125.         if task_num is not None:
  126.             self.poems[task_num] = poem
  127.  
  128.         self.poetry_count -= 1
  129.  
  130.         if self.poetry_count == 0:
  131.             self.report()
  132.             from twisted.internet import reactor
  133.             reactor.stop()
  134.    
  135.  
  136.     def report(self):
  137.         for i in self.poems:
  138.             print 'Task %d: %d bytes of poetry' % (i, len(self.poems[i]))
  139.            
  140.  
  141.     def clientConnectionFailed(self, connector, reason):
  142.         print 'Failed to connect to:', connector.getDestination()
  143.         self.poem_finished()
  144.  
  145.  
  146. def poetry_main():
  147.     addresses = parse_args()
  148.  
  149.     start = datetime.datetime.now()
  150.     # builds client instance of protocol
  151.     factory = PoetryClientFactory(len(addresses))
  152.  
  153.     from twisted.internet import reactor
  154.  
  155.     for address in addresses:
  156.         host, port = address
  157.         # connect a tcp client with (host, port) and factory
  158.         # raises some callbacks like clientCOnnectionFailed or --made
  159.         reactor.connectTCP(host, port, factory)
  160.  
  161.     reactor.run()
  162.  
  163.     elapsed = datetime.datetime.now() - start
  164.  
  165.     print 'Got %d poems in %s' % (len(addresses), elapsed)
  166.  
  167.  
  168. if __name__ == '__main__':
  169.     poetry_main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement