Как закрыть сокет, оставленный открытым убитой программой? - PullRequest
36 голосов
/ 03 мая 2011

У меня есть приложение Python, которое открывает простой сокет TCP для связи с другим приложением Python на отдельном хосте.Иногда программа либо выдает ошибку, либо я ее напрямую уничтожаю, и в любом случае сокет может оставаться открытым в течение некоторого неизвестного времени.

При следующем запуске программы я получаю эту ошибку:

socket.error: [Errno 98] Address already in use

Теперь программа всегда пытается использовать один и тот же порт, поэтому кажется, что он все еще открыт.Я проверил и уверен, что программа не работает в фоновом режиме, но мой адрес все еще используется.

ТАК, как я могу вручную (или иным образом) закрыть сокет / адрес, чтобы моя программа могланемедленно повторно использовать его?

Обновление

Основываясь на ответе Майка, я проверил страницу 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.

Ответы [ 3 ]

37 голосов
/ 03 мая 2011

Предположим, ваш сокет имеет имя s ... вам нужно установить socket.SO_REUSEADDR на сокете сервера перед привязкой к интерфейсу ... это позволит вам немедленно перезапустить TCP-сервер ...

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ADDR, PORT))
11 голосов
/ 04 мая 2011

Возможно, вы захотите попробовать использовать Twisted для вашей сети.Майк дал правильный низкоуровневый ответ, SO_REUSEADDR, но он не упомянул, что это не очень хороший вариант для установки в Windows.Это та вещь, о которой Twisted заботится о вас автоматически.Существует множество примеров скучных низкоуровневых деталей, на которые вы должны обратить внимание при непосредственном использовании модуля сокетов, но о которых вы можете забыть, если используете библиотеку более высокого уровня, такую ​​как Twisted.

5 голосов
/ 04 мая 2011

Вы путаете сокеты, соединения и порты.Сокеты - это конечные точки соединений, которые, в свою очередь, представляют собой 5 кортежей {протокол, локальный-ip, локальный-порт, удаленный-ip, удаленный-порт}.Гнездо убитой программы было закрыто ОС, и то же самое для соединения.Единственная реликвия соединения - это одноранговый сокет и соответствующий порт на одноранговом хосте.Так что вы должны спросить о том, как повторно использовать локальный порт. На что ответ SO_REUSEADDR согласно другим ответам.

...