2

これは私が持っているものです:

http.py:

class HTTPServer():

    def __init__(self, port):
        self.port = port
        self.thread = None
        self.run = True
    def serve(self):
        self.thread = threading.Thread(target=self._serve)
        self.thread.start()
    def _serve(self):
        serverAddress = ("", self.port)
        self.server = MyBaseHTTPServer(serverAddress,MyRequestHandler)
        logging.log(logging.INFO, "HTTP server started on port %s"%self.port)
        while self.run:
            self.server.handle_request()
    def stop(self):
        self.run = False
        self.server.server_close()

次に、別のファイルで、再起動します。

def restartHTTP(self):
    try:
        self.httpserver.stop()
        reload(http)
        self.httpserver = http.HTTPServer(80)
        self.httpserver.serve()
    except:
        traceback.print_exc()

これにより、アドレスが既に使用されているというエラーが表示されるため、HTTP サーバーが適切に停止していないようです。それを止めるために他に何をする必要がありますか?

編集:

restartHTTP を呼び出す場所:

def commandHTTPReload(self, parts, byuser, overriderank):
    self.client.factory.restartHTTP()
    self.client.sendServerMessage("HTTP server reloaded.")

コマンドが送信するはずのメッセージを取得したため、コマンドが実行されていることがわかります。

4

2 に答える 2

3

ポートを閉じた直後に、本当にポートを再利用したいことをOSに通知する必要があります。通常、余分なパケットが表示された場合に備えて、しばらくの間は閉じた状態で保持されます。これはSO_REUSEADDRで行います。

mysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

..mysocketを開いた後。HTTPServerでこれを行うのに適した場所は、オーバーライドされたserver_bindメソッドです。

def server_bind(self):
    HTTPServer.server_bind(self)
    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

編集:コードを詳しく調べてみると、スレッドモデルもここで問題を引き起こしている可能性が高いことがわかります。他のスレッドが同じソケット(in)での接続を待機している間に、main(?)スレッドのソケットを閉じていますaccept()。この配置には明確に定義されたセマンティクスがなく、OSごとに異なることを行うと思います。いずれにせよ、混乱を最小限に抑えるために避けるべきものです(マルチスレッドプログラムではすでに多くのことが回避されています)。古いスレッドは、接続を取得して要求を処理するまで実際には消えません(それself.runまで再チェックされないため)。そのため、ポートはそれ以降まで再バインドできない場合があります。

これに対する単純な解決策は実際にはありません。スレッド間に通信パイプを追加し、サーバースレッドでselect()/を使用poll()していずれかのスレッドでのアクティビティを待機するかaccept()、短時間後に呼び出しをタイムアウトして、self.runより頻繁にチェックされるようにすることができます。または、メインスレッドをリスニングソケット自体に接続することもできます。しかし、何をするにしても、apache、lighttpd、Tornado、Twistedなど、独自のフレームワークを使用するのではなく、「実際の」httpdまたはネットワークフレームワークを使用して検討する必要がある複雑さのレベルに近づいている可能性があります。

于 2012-05-22T16:59:55.947 に答える
1

HTTPServer を正常に停止してソケットを閉じるには、次を使用する必要があります。

# Start server
httpd = HTTPServer(...)
httpd.serve_forever()
# Stop server
httpd.shutdown()
httpd.server_close()
于 2017-02-13T15:51:48.370 に答える