2013-11-28 50 views
0

我在thisthis的幫助下構建了一個小型多線程Web服務器。然而,我的服務器線程只運行一次並停止,而不是永遠運行。以下是我的代碼:爲什麼我的多線程Python webserver失敗?

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) 

當我運行上面的腳本,我得到以下幾點:

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

如果我讓我的服務器非多線程[即它不會有一個服務器線程,那麼它運行良好]。請注意,這將產生一個新的線程爲每個請求

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) 

回答

1

你的主線程需要的東西塊還是多線程的。否則它只需撥打server_thread.start(),然後繼續撥打電話print "Server stopped - ...

考慮在您的print "Server Started...行之後加上server_thread.join()

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

+0

你能給我一個例子或解釋這個的任何鏈接?查看官方文檔代碼,似乎請求是在服務器啓動後從同一個腳本發送的。所以它執行那些然後關閉。我如何用我的代碼實現同樣的功能? – avi

+0

@avi更新回答 – kkurian

0

看到the docs

線程可以被標記爲「守護線程」。這個標誌的意義在於,只有守護進程線程退出時,整個Python程序纔會退出。

因此,當您的主線程以print "Server Stopped ...調用結束時,所有守護程序線程都會關閉。

最短,但可能不是最好的解決方案,暫停執行流程並等待鍵盤中斷,添加無限循環。你的守護線程將會在你的主線程中靜靜地死去。

try: 
    while True: 
     time.sleep(1) 
except (KeyboardInterrupt, SystemExit): 
    print "Server Stopped - %s:%s" % (HOST_NAME, PORT_NUMBER) 
+0

我沒有設置守護線程值爲true。它有效,但並不完全符合我所希望的。它首先打印它啓動並立即打印它停止。然後我發送了一個請求,它做出了迴應。而且鍵盤中斷並沒有阻止它,而是我不得不強行關閉終端。 – avi

+0

當我現在運行時,我評論到了這一行:P – avi

+0

「並且它不控制守護進程的執行流程」,是的,那麼如何控制它?併爲我的壞英語感到抱歉。 – avi