複数のポートでリッスンする Python HTTP サーバーを作成するにはどうすればよいですか?
質問
私は、BaseHTTPServer と BaseHTTPServer.BaseHTTPRequestHandler のカスタム サブクラスを使用して、Python で小さな Web サーバーを作成しています。これを複数のポートでリッスンさせることは可能ですか?
私が今やっていること:
class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def doGET
[...]
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
pass
server = ThreadingHTTPServer(('localhost', 80), MyRequestHandler)
server.serve_forever()
解決
もちろん;それぞれ同じハンドラーを使用する 2 つの異なるスレッドの 2 つの異なるポートで 2 つの異なるサーバーを起動するだけです。これは、私が作成してテストしたばかりの完全な実際に動作する例です。このコードを実行すると、両方の場所で Hello World Web ページを取得できるようになります。 http://ローカルホスト:1111/ そして http://ローカルホスト: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)
アップデート:
これは Python 3 でも機能しますが、次の 3 行を少し変更する必要があります。
from socketserver import ThreadingMixIn
from http.server import HTTPServer, BaseHTTPRequestHandler
そして
self.wfile.write(bytes("Hello World!", "utf-8"))
他のヒント
これほど単純なものにスレッドを作成するのはやりすぎだと思います。何らかの形式の非同期プログラミングを使用することをお勧めします。
以下は使用例です ツイスト:
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()
また、メインスレッドで 1 つのポートを処理し、追加のスレッドでもう 1 つのポートを処理するのではなく、各ポートを同じ方法で処理する方がはるかにすっきりすると思います。おそらくこれはスレッドの例で修正できますが、その場合は 3 つのスレッドを使用することになります。
簡単ではありません。ThreadingHTTPServer インスタンスを 2 つ用意して、独自の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()