Как закрыть сокет, оставленный открытым убитой программой?
У меня есть приложение Python, которое открывает простой TCP-сокет для связи с другим приложением Python на отдельном хосте. Иногда программа будет либо ошибкой, либо я сразу ее убью, и в любом случае сокет может оставаться открытым в течение неизвестного времени.
При следующем запуске программы я получаю эту ошибку:
socket.error: [Errno 98] Address already in use
Теперь программа всегда пытается использовать один и тот же порт, поэтому он выглядит так, как будто он все еще открыт. Я проверил и уверен, что программа не работает в фоновом режиме, но мой адрес все еще используется.
SO, как я могу вручную (или иначе) закрыть сокет/адрес, чтобы моя программа могла его повторно использовать повторно?
Обновление
Основываясь на ответе Майка, я проверил страницу socket(7)
и посмотрел на SO_REUSEADDR:
SO_REUSEADDR
Indicates that the rules used in validating addresses supplied in a bind(2) call should
allow reuse of local addresses. For AF_INET sockets this means that a socket may bind,
except when there is an active listening socket bound to the address. When the listen‐
ing socket is bound to INADDR_ANY with a specific port then it is not possible to bind
to this port for any local address. Argument is an integer boolean flag.
Ответы
Ответ 1
Предположим, что ваш сокет имеет имя s
... вам нужно установить socket.SO_REUSEADDR
на сокет сервера перед привязкой к интерфейсу... это позволит вам немедленно перезапустить TCP-сервер...
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ADDR, PORT))
Ответ 2
Возможно, вы захотите попробовать использовать Twisted для вашей сети. Майк дал правильный низкоуровневый ответ SO_REUSEADDR
, но он не упомянул, что это не очень хороший вариант для Windows. Это то, что Twisted заботится о вас автоматически. Есть много и много других примеров такого рода скучных низкоуровневых деталей, на которые вы должны обратить внимание при непосредственном использовании модуля сокета, но о которых вы можете забыть, если вы используете библиотеку более высокого уровня, такую как Twisted.
Ответ 3
Вы путаете сокеты, соединения и порты. Сокеты - это конечные точки соединений, которые, в свою очередь, являются 5-кортежами {протокол, локальный-ip, локальный-порт, удаленный-ip, удаленный-порт). Запущенный программный сокет был закрыт операционной системой, а также соединение. Единственной реликвией соединения является одноранговый сокет и соответствующий порт на узле-узле. Так что вы действительно должны спрашивать о том, как повторно использовать локальный порт. На что ответ SO_REUSEADDR соответствует другим ответам.