Я пытаюсь запрограммировать TCPServer с потоками (ThreadingMixIn) в Python. Проблема в том, что я не могу его правильно выключить, так как получаю socket.error: [Errno 48] Адрес уже используется
, когда я пытаюсь запустить его снова. Это минимальный пример кода 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 . Для этого необходимо предоставить (поддельный) сервер, к которому должно подключаться мое программное обеспечение.
изменить :
Я только что нашел наиболее правильный ответ на свою проблему: мне нужно добавить fake_server.server_close ()
в конец моего основного кода выполнения (сразу после fake_server.shutdown ()
). Я нашел его в исходном файле реализации TCPServer
. Все, что он делает, - это self.socket.close ()
.