Я пытаюсь запрограммировать TCPServer с потоками (ThreadingMixIn) в Python.Проблема в том, что я не могу выключить его должным образом, поскольку я получаю socket.error: [Errno 48] Address already in use
, когда я пытаюсь запустить его снова.Это минимальный пример кода Python, который вызывает проблему:
import socket
import threading
import SocketServer
class FakeNetio230aHandler(SocketServer.BaseRequestHandler):
def send(self,message):
self.request.send(message+N_LINE_ENDING)
def handle(self):
self.request.send("Hello\n")
class FakeNetio230a(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
self.allow_reuse_address = True
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
if __name__ == '__main__':
for i in range(2):
fake_server = FakeNetio230a(("", 1234), FakeNetio230aHandler)
server_thread = threading.Thread(target=fake_server.serve_forever)
server_thread.setDaemon(True)
server_thread.start()
# might add some client connection here
fake_server.shutdown()
Все, что должен сделать основной код, - это запустить сервер, завершить работу и запустить его снова.Но это вызывает ошибку, указанную выше, потому что сокет не был освобожден после первого выключения.
Я думал, что установка self.allow_reuse_address = True
может решить проблему, но это не сработало.Когда программа python завершает работу, я могу сразу же запустить ее снова, и она может запустить сервер один раз (но снова не дважды).
Однако проблема исчезла, когда я рандомизировал порт (например, заменил 1234
на 1234+i
), поскольку ни один другой сервер не прослушивает этот адрес.
Существует аналогичный SO Q Изящное завершение работы с ThreadingTCPServer , но решение (для allow_reuse_address
установлено значение True
не работает длямой код и я не использую ThreadingTCPServer).
Как мне изменить код, чтобы иметь возможность дважды запустить сервер в моем коде?
Дополнительная информация: причина, по которой я это делаю, заключается в том, что я хочу запустить некоторые модульные тесты для своего проекта на python.Это требует предоставления (поддельного) сервера, к которому должно подключаться мое программное обеспечение.
edit :
Я только что нашел самый правильный ответ на мою проблему: я должен добавить fake_server.server_close()
в конце основного кода выполнения (сразу после fake_server.shutdown()
).Я нашел это в исходном файле реализации TCPServer
.Все, что он делает, это self.socket.close()
.