A while back, I showed you how to create a simple HTTP server using Python. Since that post, I have received literally hundreds of emails asking for help building web servers using Python that are a little more robust than the simple web server shown in that article. One of the biggest issues with the code in that article is that it is synchronous. That means that every request made to the server has to be processed one at a time and in the order they are received. If several requests are made at the same time or within the same time the server is processing other requests, each request must wait in line until all previous requests have been processed. To handle simultaneous requests, we need to implement a different type of server, a server that is asynchronous and more importantly, non-blocking. Servers that are non-blocking are those that are capable of processing multiple requests at the same time without blocking other requests from coming in while others are being processed.
Typically I would walk you through every individual line of code used in my articles. But, in this article, I’m only going to discuss the important pieces. If you have any questions about anything not mentioned in this article, be sure to post your questions in the comments below and I’ll be glad to help you out. The first piece of the application is the “asyncore” library. This library gives us the power to continuously listen for requests without doing the actual processing of each request. Instead of processing each request within the same method that listens for requests, you will hand off the processing work to another thread where the work will be done and handed back to the listening thread once all of the work is complete.
The second piece of the application that you should understand is the method “handle_read”. This method is used to handle all “GET” requests. For example, if you click a link that has parameters appended to the end of the URL, this will initiate a “GET” request on the server. In this application, the “handle_read” method will get the parameters from the URL where they can be used within the application. If you want to create a page that has a form with some input fields on it and you want to process those fields using this application, you will need to implement the “handle_write” method. However, the “handle_write” method requires a lot more work than the simple “handle_read” method. I’ll show how to use the “handle_write” method in another article. Until then, here is the code needed for an asynchronous HTTP server with Python. Enjoy!
import asyncore, socket class HTTPHandler(asyncore.dispatcher): def __init__(self, client, addr, server): asyncore.dispatcher.__init__(self, client) def handle_read(self): data = self.recv(1024) self.send('HTTP/1.1 200 OK\n\n<html><head></head><body>Hello world!!!</body></html>') self.close() class HTTPServer(asyncore.dispatcher): def __init__(self, addr): self.addr = addr asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(self.addr) self.listen(5) print 'Listening on port %d' % addr def handle_accept(self): (client, addr) = self.accept() print 'Request from %s:%s' % (addr, addr) HTTPHandler(client, addr, self) if __name__ == '__main__': server = HTTPServer(('', 8080)) asyncore.loop()
To test this application, run it and point your browser to http://localhost:8080. When you do, you should be presented with the words “Hello world!!!”
PayPal will open in a new tab.