Восстановление из zmq.error.ZMQError: адрес уже используется

Я нажимаю Ctrl-C при запуске соединения PAIR (неблокирующих клиентских серверов) с ZMQ. Позже, когда я попытался запустить шаблон REQ-REP (блокирование клиентского подключения к одному серверу), я продолжаю получать ошибку Address already in use. Я попытался запустить netstat с помощью netstat -ltnp | grep :<my port>, но это не указывает какой-либо процесс.

Итак, кто именно использует этот адрес?

Также как можно изящно отключить такие подключения сокетов?

Ответ 1

Вопрос 1:

Если вы выполняете sudo netstat -ltnp, в операционной системе типа Linux вы, скорее всего, увидите процесс, владеющий портом. Убейте его с помощью kill -9 <pid>.

Вопрос 2:

Когда вы выходите из программы, закройте свои сокеты, а затем вызовите zmq_ctx_destroy(). Это разрушает контекст. Подробнее см. http://zguide.zeromq.org/page:all#toc17.

Ответ 2

В этот самый момент:

reboot

Далее:

начните использовать конструкторы инкапсуляции try:/except:/finally:, которые помогут вам предоставить изящный выход из всех распределений zmq, в т.ч. все Socket-ы .close() и Context .term() без каких-либо зависших сирот (-ов), утечки памяти, даже в том случае, если какая-либо кнопка паники или необработанное исключение прерывает выполнение вашего кода вместе с потерей ссылок на ваше все еще зависание, сетевое аппаратное обеспечение, экземпляры.

Ответ 3

Иногда другой процесс, использующий zeromq, поддерживает использование порта, а netstat не указывает, что другое прослушивание процесса (поэтому netstat -lntp не покажет его), а скорее показывает установленное соединение на порту с тот же хост/порт на обоих концах. После уничтожения этого другого процесса порт теперь доступен для использования.

Причина № 1: У меня это произошло, потому что у меня были порты прослушивания zeromq, настроенные в диапазоне эфемерных портов (на linux, например 32768-61000), которые используются в качестве локальной стороны исходящих подключений, а также мои сервисы необходимо подключиться к другим службам в одном окне. Процент от времени, когда исходящее соединение получает эфемерный порт, который совпадает с портом прослушивания на поле, и вдруг "адрес уже используется". Я просто переместил все прослушивающие порты в сторону эфемерного диапазона портов, и все проблемы "адрес уже используется" исчезли.

Причина № 2: Спекуляция. Когда я столкнулся с аналогичными проблемами с другими сетевыми библиотеками python, процесс нарушения был ранее запущен из процесса прослушивания с использованием подпроцесса или подобного, и возникла проблема с утечкой сокета дочернему устройству обработать; если родительский процесс вышел без закрытия сокета, сокет остался бы в живых и принадлежал дочернему процессу, и хотя дочерний процесс действительно ничего не знал о сокете, он все равно оставался бы таким, чтобы другие процессы не могли используйте его.

Если это проблема, она может быть исправлена ​​путем настройки флагов сокета перед подпроцессом, например. (Unix-специфический):

fd = sock.get(zmq.FD)
old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)

Или, может быть, есть способ более правильно закрыть сокет в родительском процессе.