我正在使用BaseHTTPServer和BaseHTTPServer.BaseHTTPRequestHandler的自定义子类在Python中编写一个小型Web服务器.是否可以在多个端口上进行监听?
我现在在做什么:
class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def doGET [...] class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): pass server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler) server.serve_forever()
Eli Courtwri.. 34
当然; 只需在两个不同线程的两个不同端口上启动两个不同的服务器,每个线程使用相同的处理程 这是我刚刚编写和测试的完整,有效的示例.如果您运行此代码,那么您将能够在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): daemon_threads = True 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)
更新:
这也适用于Python 3,但需要稍微更改三行:
from socketserver import ThreadingMixIn from http.server import HTTPServer, BaseHTTPRequestHandler
和
self.wfile.write(bytes("Hello World!", "utf-8"))
Thomas Vande.. 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()
我还认为以相同的方式处理每个端口看起来更清晰,而不是让主线程处理一个端口而另一个线程处理另一个端口.可以说这可以在线程示例中修复,但是你使用了三个线程.
当然; 只需在两个不同线程的两个不同端口上启动两个不同的服务器,每个线程使用相同的处理程 这是我刚刚编写和测试的完整,有效的示例.如果您运行此代码,那么您将能够在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): daemon_threads = True 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)
更新:
这也适用于Python 3,但需要稍微更改三行:
from socketserver import ThreadingMixIn from http.server import HTTPServer, BaseHTTPRequestHandler
和
self.wfile.write(bytes("Hello World!", "utf-8"))
我会说,对这种简单的东西进行线程化是过度的.你最好使用某种形式的异步编程.
以下是使用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()
我还认为以相同的方式处理每个端口看起来更清晰,而不是让主线程处理一个端口而另一个线程处理另一个端口.可以说这可以在线程示例中修复,但是你使用了三个线程.
不容易.您可以有两个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()