0

I have built a small multithreaded web server with help of this and this. However my server thread runs only once and stops, instead of running forever. Following is my code :

import time
import BaseHTTPServer
import urlparse
import urllib 
import SocketServer
import threading

HOST_NAME = 'localhost'
PORT_NUMBER = 8089


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_HEAD(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def do_GET(self):
        """ Respond to a GET request. """

        self.do_HEAD()

        if self.path == '/vmnum/':
            response = self.construct_message('Currently there are no VMs running')
            self.wfile.write(response)
        elif self.path == '/vmname/':
            respose = self.construct_message('Your VM is yet to be named')
            self.wfile.write(respose)
        else:
            response = self.construct_message()
            self.wfile.write(response)
        return


    def do_POST(self):
        """ Respond to a POST request """
        length = int(self.headers['Content-Length'])

        #http://stackoverflow.com/a/12731208/1382297
        post_data = urlparse.parse_qs(self.rfile.read(length).decode('utf-8'))
        thread_number = threading.currentThread().getName()
        lab_name = str(post_data.get('lab-name')[0])
        lab_author = str(post_data.get('lab-author')[0])

        message = "<p>You successfully created a VM named: " + lab_name + " at the location: " + lab_author + "</p><p>\
        \nYou have been served from the thread: " + thread_number
        respose = self.construct_message(message)

        self.wfile.write(respose)        
        return

    def construct_message(self, message=''):
        message_part1 = "<html><head><title>One VM Per Lab</title></head><body><p>Success!</p>"
        message_part2 = "<p>You accessed path: " + self.path + "</p>"
        message_part3 = "</body></html>"
        return message_part1 + message_part2 + message + message_part3

class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
    """Handle requests in a separate thread."""
    pass

if __name__ == '__main__':
    httpd = ThreadedHTTPServer((HOST_NAME, PORT_NUMBER), Handler)
    try:
        server_thread = threading.Thread(target=httpd.serve_forever)
        # Exit the server thread when the main thread terminates
        server_thread.daemon = True
        server_thread.start()
        print "Server Started - %s:%s with the thread :%s" % (HOST_NAME, PORT_NUMBER, server_thread.name)
    except KeyboardInterrupt:
        httpd.server_close()
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER)

When I run the above script, I get the following:

Server Started - localhost:8089 with the thread :Thread-1
Server Stopped - localhost:8089

If I make my server non-multithreaded [i.e. it won't have a server thread, then it runs fine]. Note that it will be still multithreaded by spawning a new thread for every request

if __name__ == '__main__':
    httpd = ThreadedHTTPServer((HOST_NAME, PORT_NUMBER), Handler)
    print "Server Started - %s:%s" % (HOST_NAME, PORT_NUMBER)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        httpd.server_close()
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER)
avi
  • 9,292
  • 11
  • 47
  • 84

2 Answers2

1

Your main thread needs to block on something. Otherwise it just calls server_thread.start() and then proceeds right along to calling print "Server stopped - ....

Consider putting a server_thread.join() after your print "Server Started... line.

See also http://docs.python.org/2/library/threading.html#threading.Thread.join

kkurian
  • 3,844
  • 3
  • 30
  • 49
  • can you give me a example or any link that explains this? Looking official docs code, it seems requests are sent from the same script after the server has been started. So it executes those and then shutsdown. How do I achieve same thing with my code? – avi Nov 28 '13 at 19:34
0

From the docs:

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left.

So as your main thread terminates with print "Server Stopped ... call, all your daemon threads are shut down.

Shortest, but probably not the best solution to pause execution flow and wait to keyboard interrupt, add infinite loop. Your daemon thread will die silently with your main thread.

try:
   while True:
       time.sleep(1)
except (KeyboardInterrupt, SystemExit):
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER)
alko
  • 46,136
  • 12
  • 94
  • 102
  • I did not set daemon thread value to true. It works, but not exactly what I am hoping for. It first prints that it is started and immediately prints that it is stopped. Then I sent a request, it responded. And also keyboard interrupt did not stop it, rather I had to force close the terminal. – avi Nov 28 '13 at 19:31
  • I commented that line when I ran now :P – avi Nov 28 '13 at 19:37
  • "and it do not control daemons process execution flow", yes, so how do I control it? and sorry for my bad english. – avi Nov 28 '13 at 19:38
  • I want to create a new thread for the httpd. Now it is running single threaded, when it is run, it should spawn a server thread to serve the requests. – avi Nov 28 '13 at 19:42