This server is an HTTP wrapper around the asyncode module. 1) It can handle HTTP versions 0.9, 1.0, and 1.1 but, I will make no claim that it will handle all the corner cases. 2) It will handle Keep-Alive correctly for version 1.0 and 1.1, there is no keep alive for 0.9. 3) It will not handle pipe-lining for version 1.1 (Queuing multiple requests before responding to any of them). 4) There is a script in the /tests directory named testACHTTPServer.py which is used to test the AsyncoreHTTPServer module. a) The are the maximum requests with none dropped. Connection: keep-alive ---------------------- The statistics for this server using the arguments below are, where localhost:8081 is the host:port, HEAD or GET is the HTTP method on the server, 165 is the number of times to repeat the request, 15.0 is the socket timeout while waiting for a new connection, and True is to keep alive the connection after each request. $ time ./testACHTTPServer.py -h localhost:8081 -m [HEAD|GET] -p / -c 165 \ -t 15.0 -k True 1) Six separate runs using HEAD averaged 0.301 seconds which is 548 requests per second. 2) Six separate runs using GET averaged 0.354 seconds which is 466 requests per second. Connection: close ----------------- The statistics for this server using the arguments below are, where localhost:8081 is the host:port, HEAD or GET is the HTTP method on the server, 45 is the number of times to repeat the request, 15.0 is the socket timeout while waiting for a new connection, and False is to not keep alive the connection after each request. $ time ./testACHTTPServer.py -h localhost:8081 -m [HEAD|GET] -p / -c 45 \ -t 15.0 -k False 1) Six separate runs using HEAD averaged 0.161 seconds which is 280 requests per second. 2) Six separate runs using Get averaged 0.177 seconds which is 254 requests per second. Conclusion ---------- If the connection is kept alive many more requests to the same resource can handled sequentially without dropping any connections. This shows that AsyncoreHTTPServer can keep up with a very fast client if the connection is kept alive. Wrapping AsyncoreHTTPServer =========================== Below is an example of how to wrap AsyncoreHTTPServer so AsyncoreHTTPServer can be used in a stand alone application. class StandAloneServer(AsyncoreHTTPServer): def __init__(self): # Flag to tell the server to exit from a forever loop. self.__exit = False def start(self, host, port, handler=StandAloneHandler): """ Start the server. @param host: The host to run on. @param port: The port to run on. @param handler: The request handler to use. This handler should wrap either AsyncoreHTTPRequestHandler or WSGIAsynHandler. """ msg = "The Stand Alone Service is up for business..." AsyncoreHTTPServer.__init__(self, host, port, handler, logger="StandAlone", httpTimeout=300) self.setBacklog(5) for count in range(10): try: AsyncoreHTTPServer.start(self) print "\n%s" % msg break except socket.error, e: print "%s: %s, will try again in one minute." % \ (sys.argv[0], e[1])) time.sleep(60) def serve_forever(self, timeout=30.0): """ This method will only exit when self.__exit is True. """ while not self.__exit: self.loop(timeout=timeout) def exitServer(self, signum, frame): """ Exit the server. Callback for the signal handler. @param signum: A number representing the signal to catch. @param frame: The current stack frame (None or a frame object) """ print "%s: Caught signal %s exiting Template Service." % \ sys.argv[0], signum) self.__exit = True self.closeAllChannels() Then this would be called like so: if __name__ == '__main__': import traceback, signal # Get the host and port from somewhere. host = 'localhost' port = 80 try: ts = StandAloneServer() signal.signal(signal.SIGTERM, ts.exitServer) ts.start(host, port) ts.serve_forever() except Exception: print "%s: %s\n" % (sys.exc_info()[0], sys.exc_info()[1]) tb = sys.exc_info()[2] traceback.print_tb(tb) sys.exit(1) sys.exit(0) =============================================== If there are any questions feel free to ask me. Carl J. Nobile mailto:carl.nobile@gmail.com