这就是我所拥有的:
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 服务器没有正确停止。我还需要做什么来阻止它?
EDIT:
我在哪里调用 restartHTTP:
def commandHTTPReload(self, parts, byuser, overriderank):
self.client.factory.restartHTTP()
self.client.sendServerMessage("HTTP server reloaded.")
我确实知道该命令正在执行,因为我收到了它应该发送的消息。
您只需让操作系统知道您确实希望在关闭端口后立即重用该端口。通常它会保持关闭状态一段时间,以防出现任何额外的数据包。您可以使用 SO_REUSEADDR 执行此操作:
mysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
..打开 mysocket 后。使用 HTTPServer 执行此操作的好地方可能是在重写的server_bind
method:
def server_bind(self):
HTTPServer.server_bind(self)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
编辑:更仔细地查看您的代码后,我发现您的线程模型也可能在这里引起问题。您正在主(?)线程中关闭套接字,而另一个线程正在等待同一套接字上的连接(在accept()
)。这种安排没有明确定义的语义,我相信它在不同的操作系统上会做不同的事情。无论如何,为了最大程度地减少混乱(在多线程程序中已经存在很多这样的情况),您应该避免这种情况。您的旧线程实际上不会消失,直到它获得连接并处理其请求之后(因为它不会重新检查self.run
直到那时),因此在此之后该端口可能无法重新绑定。
对此确实没有一个简单的解决方案。您可以在线程之间添加通信管道,然后使用select()
/poll()
在服务器线程中等待其中任何一个的活动,或者您可以超时accept()
短时间后调用,以便self.run
被更频繁地检查。或者您可以让主线程连接到侦听套接字本身。但无论你做什么,你可能会接近复杂程度,你应该考虑使用“真正的”httpd 或网络框架,而不是滚动你自己的:apache、lighttpd、Tornado、Twisted 等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)