Подтвердить что ты не робот

Как закрыть сокет, оставленный открытым убитой программой?

У меня есть приложение 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.
4b9b3361

Ответ 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 соответствует другим ответам.