2008-09-13 218 views
14

我正在用Python編寫一個小型Web服務器,使用BaseHTTPServer和BaseHTTPServer.BaseHTTPRequestHandler的自定義子類。是否有可能讓這個監聽多個端口?如何編寫python HTTP服務器以偵聽多個端口?

我現在做:

class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
    def doGET 
    [...] 

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): 
    pass 

server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler) 
server.serve_forever() 

回答

28

把握;只需在兩個不同線程的兩個不同端口上啓動兩個不同的服務器,每個線程使用相同的處理程序。這是我剛剛編寫和測試的一個完整的工作示例。如果你運行該代碼,那麼你就可以在兩個http://localhost:1111/http://localhost:2222/

from threading import Thread 
from SocketServer import ThreadingMixIn 
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 

class Handler(BaseHTTPRequestHandler): 
    def do_GET(self): 
     self.send_response(200) 
     self.send_header("Content-type", "text/plain") 
     self.end_headers() 
     self.wfile.write("Hello World!") 

class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): 
    pass 

def serve_on_port(port): 
    server = ThreadingHTTPServer(("localhost",port), Handler) 
    server.serve_forever() 

Thread(target=serve_on_port, args=[1111]).start() 
serve_on_port(2222) 
+0

GIL可以嗎? – sashab 2012-04-03 14:40:47

+1

@scrat:GIL對於這段代碼無關緊要,因爲這段代碼大部分都是I/O綁定的,而且Python中的大部分I/O都是使用釋放GIL的低級C庫編寫的。與大多數性能問題一樣,我的建議是不要擔心它,除非您已經對代碼進行了基準測試並確定它確實是一個問題。 – 2012-04-03 15:24:42

4

不容易得到一個Hello World網頁。你可以有兩個ThreadingHTTPServer實例,編寫你自己的serve_forever()函數(不要擔心它不是一個複雜的函數)。

現有的功能:

def serve_forever(self, poll_interval=0.5): 
    """Handle one request at a time until shutdown. 

    Polls for shutdown every poll_interval seconds. Ignores 
    self.timeout. If you need to do periodic tasks, do them in 
    another thread. 
    """ 
    self.__serving = True 
    self.__is_shut_down.clear() 
    while self.__serving: 
     # XXX: Consider using another file descriptor or 
     # connecting to the socket to wake this up instead of 
     # polling. Polling reduces our responsiveness to a 
     # shutdown request and wastes cpu at all other times. 
     r, w, e = select.select([self], [], [], poll_interval) 
     if r: 
      self._handle_request_noblock() 
    self.__is_shut_down.set() 

所以我們更換會是這樣的:

def serve_forever(server1,server2): 
    while True: 
     r,w,e = select.select([server1,server2],[],[],0) 
     if server1 in r: 
      server1.handle_request() 
     if server2 in r: 
      server2.handle_request() 
6

我要說的是線程的東西,這個簡單的是矯枉過正。你最好使用某種形式的異步編程。

下面是一個例子使用Twisted

from twisted.internet import reactor 
from twisted.web import resource, server 

class MyResource(resource.Resource): 
    isLeaf = True 
    def render_GET(self, request): 
     return 'gotten' 

site = server.Site(MyResource()) 

reactor.listenTCP(8000, site) 
reactor.listenTCP(8001, site) 
reactor.run() 

我也認爲它看起來會更加清晰讓每個端口以同樣的方式來處理,而不必在主線程處理一個端口和一個額外的線程,處理另一個。可以說,這可以在線程示例中修復,但是接下來使用三個線程。