如何编写python HTTP服务器以侦听多个端口?
时间:2020-03-05 18:52:46 来源:igfitidea点击:
我正在使用Python使用BaseHTTPServer和BaseHTTPServer.BaseHTTPRequestHandler的自定义子类编写小型Web服务器。是否可以使它在多个端口上侦听?
我现在在做什么:
class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def doGET [...] class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): pass server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler) server.serve_forever()
解决方案
回答
当然;只需在两个不同线程中的两个不同端口上启动两个不同服务器,每个线程都使用相同的处理程序。这是我刚刚编写并测试的一个完整的,有效的示例。如果运行此代码,则可以在http:// localhost:1111 /和http:// localhost:2222 /处获得Hello World网页。
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)
回答
不容易。我们可以有两个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()
回答
我要说的是,为这种简单的事情进行线程处理是过大的。我们最好使用某种形式的异步编程。
这是使用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()
我还认为,以相同的方式处理每个端口看起来要干净得多,而不是让主线程处理一个端口,而让另一个线程处理另一个端口。可以在线程示例中解决这个问题,但是我们使用的是三个线程。