如何编写python HTTP服务器以侦听多个端口?
问题描述:
我正在用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()
答
把握;只需在两个不同线程的两个不同端口上启动两个不同的服务器,每个线程使用相同的处理程序。这是我刚刚编写和测试的一个完整的工作示例。如果你运行该代码,那么你就可以在两个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)
答
不容易得到一个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()
答
我要说的是线程的东西,这个简单的是矫枉过正。你最好使用某种形式的异步编程。
下面是一个例子使用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()
我也认为它看起来会更加清晰让每个端口以同样的方式来处理,而不必在主线程处理一个端口和一个额外的线程,处理另一个。可以说,这可以在线程示例中修复,但是接下来使用三个线程。
GIL可以吗? – sashab 2012-04-03 14:40:47
@scrat:GIL对于这段代码无关紧要,因为这段代码大部分都是I/O绑定的,而且Python中的大部分I/O都是使用释放GIL的低级C库编写的。与大多数性能问题一样,我的建议是不要担心它,除非您已经对代码进行了基准测试并确定它确实是一个问题。 – 2012-04-03 15:24:42