Advertisement
Guest User

Untitled

a guest
Jun 8th, 2012
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.29 KB | None | 0 0
  1. # This is the Twisted Get Poetry Now! client, version 1.0.
  2.  
  3. # NOTE: This should not be used as the basis for production code.
  4. # It uses low-level Twisted APIs as a learning exercise.
  5.  
  6. import datetime, errno, optparse, socket
  7.  
  8. from twisted.internet import main
  9.  
  10.  
  11. def parse_args():
  12.     usage = """usage: %prog [options] [hostname]:port ...
  13.  
  14. This is the Get Poetry Now! client, Twisted version 1.0.
  15. Run it like this:
  16.  
  17.  python get-poetry.py port1 port2 port3 ...
  18.  
  19. If you are in the base directory of the twisted-intro package,
  20. you could run it like this:
  21.  
  22.  python twisted-client-1/get-poetry.py 10001 10002 10003
  23.  
  24. to grab poetry from servers on ports 10001, 10002, and 10003.
  25.  
  26. Of course, there need to be servers listening on those ports
  27. for that to work.
  28. """
  29.  
  30.     parser = optparse.OptionParser(usage)
  31.  
  32.     _, addresses = parser.parse_args()
  33.  
  34.     if not addresses:
  35.         print parser.format_help()
  36.         parser.exit()
  37.  
  38.     def parse_address(addr):
  39.         if ':' not in addr:
  40.             host = '127.0.0.1'
  41.             port = addr
  42.         else:
  43.             host, port = addr.split(':', 1)
  44.  
  45.         if not port.isdigit():
  46.             parser.error('Ports must be integers.')
  47.  
  48.         return host, int(port)
  49.  
  50.     return map(parse_address, addresses)
  51.  
  52.  
  53. class PoetrySocket(object):
  54.  
  55.     poem = ''
  56.  
  57.     def __init__(self, task_num, address):
  58.         self.task_num = task_num
  59.         self.address = address
  60.         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  61.         self.run = True
  62.  
  63.         try:
  64.           self.sock.connect(address)
  65.         except socket.error as err:
  66.           print 'Task %d: failed to connect to server on port %d: %s' % (self.task_num, address[1], err[1])
  67.           self.fail()
  68.           return
  69.  
  70.         self.sock.setblocking(0)
  71.  
  72.         # tell the Twisted reactor to monitor this socket for reading
  73.         from twisted.internet import reactor
  74.         reactor.addReader(self)
  75.  
  76.         self.timeout = reactor.callLater(12, self.timedout)
  77.  
  78.     def fail(self):
  79.         # clean up on failure
  80.         self.run = False
  81.  
  82.     def success(self):
  83.         # clean up on succes
  84.         self.timeout.cancel()
  85.  
  86.     def timedout(self):
  87.         print 'Task %d has timed out.' % self.task_num
  88.         self.fail()
  89.         self.connectionLost('timedout')
  90.  
  91.     def fileno(self):
  92.         try:
  93.             return self.sock.fileno()
  94.         except socket.error:
  95.             return -1
  96.  
  97.     def connectionLost(self, reason):
  98.         self.sock.close()
  99.  
  100.         # stop monitoring this socket
  101.         from twisted.internet import reactor
  102.         reactor.removeReader(self)
  103.  
  104.         # see if there are any poetry sockets left
  105.         for reader in reactor.getReaders():
  106.             if isinstance(reader, PoetrySocket):
  107.                 return
  108.  
  109.         reactor.stop() # no more poetry
  110.  
  111.     def doRead(self):
  112.         bytes = ''
  113.  
  114.         while True:
  115.             try:
  116.                 bytesread = self.sock.recv(1024)
  117.                 if not bytesread:
  118.                     break
  119.                 else:
  120.                     bytes += bytesread
  121.             except socket.error, e:
  122.                 if e.args[0] == errno.EWOULDBLOCK:
  123.                     break
  124.                 return main.CONNECTION_LOST
  125.  
  126.         if not bytes:
  127.             print 'Task %d finished' % self.task_num
  128.             self.success()
  129.             return main.CONNECTION_DONE
  130.         else:
  131.             msg = 'Task %d: got %d bytes of poetry from %s'
  132.             print  msg % (self.task_num, len(bytes), self.format_addr())
  133.  
  134.         self.poem += bytes
  135.  
  136.     def logPrefix(self):
  137.         return 'poetry'
  138.  
  139.     def format_addr(self):
  140.         host, port = self.address
  141.         return '%s:%s' % (host or '127.0.0.1', port)
  142.  
  143.  
  144. def poetry_main():
  145.     addresses = parse_args()
  146.  
  147.     start = datetime.datetime.now()
  148.  
  149.     sockets = [PoetrySocket(i + 1, addr) for i, addr in enumerate(addresses)]
  150.  
  151.     from twisted.internet import reactor
  152.     reactor.run()
  153.  
  154.     elapsed = datetime.datetime.now() - start
  155.  
  156.     for i, sock in enumerate(sockets):
  157.         print 'Task %d: %d bytes of poetry' % (i + 1, len(sock.poem))
  158.  
  159.     # only count sockets that succeeded
  160.     print 'Got %d poem(s) in %s' % (len([s for s in sockets if s.run]), elapsed)
  161.  
  162.  
  163. if __name__ == '__main__':
  164.     poetry_main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement