SHARE
TWEET

Async (non-twisted) poetry server

a guest Jul 28th, 2011 212 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. """
  2.  Async (non-twisted) poetry server
  3. """
  4.  
  5. import datetime, errno, optparse, select, socket, os, time, traceback, sys
  6.  
  7.  
  8. def parse_args():
  9.     usage = """usage: %prog [options] [hostname]:port ...
  10.  
  11. This is the Get Poetry Now! server, ASYNC edition.
  12. Run it like this:
  13.  
  14.  python my-server-5.py--host=host --port=port poetry_file
  15.  
  16. If you are in the base directory of the twisted-intro package,
  17. you could run it like this:
  18.  
  19.  python my-server/my-server-5.py --host localhost --port 10080 path/to/file
  20. """
  21.  
  22.  
  23.     parser = optparse.OptionParser(usage)
  24.  
  25.     help = "The port to listen on. Default to a random available port."
  26.     parser.add_option('--port', type='int', help=help)
  27.  
  28.     help = "The interface to listen on. Default is localhost."
  29.     parser.add_option('--host', help=help, default='localhost')
  30.  
  31.     help = "The number of seconds between sending bytes."
  32.     parser.add_option('--delay', type='float', help=help, default=.1)
  33.  
  34.     help = "The number of bytes to send at a time."
  35.     parser.add_option('--num-bytes', type='int', help=help, default=10)
  36.  
  37.     options, args = parser.parse_args()
  38.  
  39.     if len(args) != 1:
  40.         parser.error('Provide exactly one poetry file.')
  41.  
  42.     poetry_file = args[0]
  43.  
  44.     if not os.path.exists(args[0]):
  45.         parser.error('No such file: %s' % poetry_file)
  46.  
  47.     return options, poetry_file
  48.  
  49.  
  50. def send_poetry(sock, addr, inputf, clients, clients_delete_queue, num_bytes = 100, delay = 0.1):
  51.     """Send some poetry slowly down the socket."""
  52.    
  53.     bytes = inputf.read(num_bytes)
  54.    
  55.     if not bytes: # no more poetry :(
  56.         print 'Close %s (ok)' % (addr,)
  57.         return sending_finished(sock, addr, inputf, clients, clients_delete_queue)
  58.  
  59.     try:
  60.         print 'Sending %d bytes to %s' % (len(bytes), addr,)
  61.         sock.sendall(bytes) # this is a blocking call
  62.         time.sleep(delay)
  63.         return
  64.     except socket.error:
  65.         print 'Close %s (error)' % (addr,)
  66.         return sending_finished(sock, addr, inputf, clients, clients_delete_queue)
  67.  
  68. def sending_finished(sock, addr, inputf, clients, clients_delete_queue):
  69.     clients_delete_queue.append(addr[1])
  70.     clients.remove(sock)
  71.     sock.close()
  72.     inputf.close()
  73.  
  74.     return
  75.  
  76. def serve(listen_socket, poetry_file, server, clients):
  77.    
  78.    
  79.     clients_additional_data = {}
  80.     clients_delete_queue = []
  81.  
  82.  
  83.     while True:
  84.         try:
  85.             inputready, outputready, _ = select.select(server, clients, [])
  86.         except select.error, e:
  87.             print 'select error', e
  88.             break
  89.         except socket.error, e:
  90.             #print 'socket error', e
  91.             break
  92.         except ValueError, e:
  93.             print 'ValueError', e, 'server = ', len(server), 'otputs = ', len(clients)
  94.             break
  95.         except KeyboardInterrupt, e:
  96.             print 'KeyboardInterrupt', e
  97.             sys.exit(0)
  98.             break
  99.         except:
  100.             #traceback.print_stack()
  101.             print 'other error = ', sys.exc_info()[0]
  102.             break
  103.        
  104.         """
  105.          Add new clients
  106.        """
  107.         for s in inputready:
  108.             sock, addr = listen_socket.accept()
  109.             print '-' * 20
  110.             print 'added new client %s' % (addr,)
  111.             print '-' * 20
  112.  
  113.             clients.append(sock)
  114.  
  115.             inputf = open(poetry_file)
  116.             clients_additional_data[addr[1]] = (sock, addr, inputf)
  117.        
  118.         """
  119.          Remove clients if connection loosed
  120.        """
  121.         if len(clients_delete_queue):
  122.             for key in clients_delete_queue:
  123.                 print 'delete %s' % (key,)
  124.                 del clients_additional_data[key]
  125.  
  126.         clients_delete_queue = []
  127.        
  128.         """
  129.          Send data to active clients
  130.        """
  131.         for key in clients_additional_data:
  132.             sock, addr, inputf = clients_additional_data[key]
  133.             send_poetry(sock, addr, inputf, clients, clients_delete_queue)
  134.  
  135. def main():
  136.     opts, poetry_file = parse_args()
  137.    
  138.     server = []
  139.     clients = []
  140.  
  141.     print 'Server started %s:%d/%s' % (opts.host, opts.port, poetry_file)
  142.    
  143.    
  144.     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  145.     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  146.     sock.bind((opts.host, opts.port))
  147.     #sock.setblocking(0)
  148.  
  149.     sock.listen(5)
  150.    
  151.     print 'Serving on port %s.' % (sock.getsockname()[1])
  152.  
  153.     server.append(sock)
  154.    
  155.     while True:
  156.         serve(sock, poetry_file, server, clients)
  157.  
  158. if __name__ == '__main__':
  159.     main()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top