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

您只需要让操作系统知道您确实想在关闭端口后立即重用它。通常它会保持关闭状态一段时间,以防出现任何额外的数据包。您可以使用 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 accept())上的连接。这种安排没有明确定义的语义,我相信它在不同的操作系统上做不同的事情。在任何情况下,您都应该避免这种情况,以尽量减少混淆(在多线程程序中已经有很多这样的情况了)。您的旧线程实际上不会消失,直到它获得连接并处理其请求(因为它self.run直到那时才会重新检查),因此在此之后端口可能无法重新绑定。

没有一个简单的解决方案。您可以在线程之间添加一个通信管道,然后在服务器线程中使用select()/poll()来等待其中任何一个的活动,或者您可以accept()在短时间内使调用超时,以便self.run更频繁地检查。或者你可以让主线程连接到监听套接字本身。但是无论你做什么,你可能已经接近了你应该考虑使用“真正的”httpd 或网络框架而不是自己滚动的复杂程度:apache、lighttpd、Tornado、Twisted 等。

于 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 回答