Почему OS X позволяет прослушивать один и тот же TCP-порт дважды?

Я пытался отладить проблемы с распределением портов в Jenkins на OS X, прослушивая определенные порты с помощью netcat, что привело к некоторым странным результатам.


В терминале OS X 10.8.2:

$ uname -rs
Darwin 12.2.1

$ nc -l 54321

Затем во втором терминале:

$ nc -l 54321

А в третьем терминале lsof показывает, что оба экземпляра связаны с одним и тем же портом:

$ lsof -i | grep 54321
nc  70706 chris    3u  IPv4 0x55618c024692f4d1      0t0  TCP *:54321 (LISTEN)
nc  70769 chris    3u  IPv4 0x55618c0232cb8661      0t0  TCP *:54321 (LISTEN)

В Linux:

Первый терминал:

$ uname -rs
Linux 3.2.0-34-generic

$ nc -l 54321

Второй терминал:

$ nc -l 54321
nc: Address already in use

Почему OS X также не сообщает, что адрес уже используется?


person Christopher Orr    schedule 05.12.2012    source источник
comment
Я не знаю синтаксис вывода lsof -i, но что такое 0x55618c024692f4d1 и 0x55618c0232cb8661? Если это IP-адреса, то это очевидно, потому что слушатель был привязан к определенному IP-адресу, а не к любому адресу.   -  person CodeCaster    schedule 05.12.2012
comment
Это бессмысленные адреса памяти. Единственная их цель — определить, что это два разных сокета (например, не результат fork() или dup()).   -  person    schedule 05.12.2012
comment
Запуск lsof -i дает мне 27 уникальных значений для этого поля (УСТРОЙСТВО); Я считаю, что это адрес памяти. Последний столбец показывает, что сокеты привязаны к *.   -  person Christopher Orr    schedule 05.12.2012
comment
Конечно, и в любом случае они слишком длинные, чтобы быть IPv4-адресами. Я исправляюсь. :-)   -  person CodeCaster    schedule 05.12.2012


Ответы (1)


Двоичный файл в OS X устанавливает параметр сокета SO_REUSEPORT, который позволяет полностью дублировать привязки (setsockopt в OS X). Вы можете проверить это, используя dtrace на OS X.

Двоичный файл netcat в Linux этого не делает, поэтому вы получите ошибку привязки, как и ожидалось. Опять же, вы можете убедиться в этом, используя strace. Я считаю, что SO_REUSEPORT устарел или даже недоступен в более новых ядрах Linux.

person Neal    schedule 06.12.2012
comment
Спасибо за информацию! Это также объясняет, почему, если работало другое программное обеспечение, nc делал сообщение о том, что порт уже используется. - person Christopher Orr; 07.12.2012
comment
Для информации: параметр сокета SO_REUSEPORT был добавлен в Linux 3.9: lwn.net/Articles/542629 - person Christopher Orr; 28.05.2015
comment
Это полезно, однако можете ли вы привести пример dtrace, который может помочь программисту подтвердить это? Примеры, которые я нашел в Интернете, немногочисленны и немного трудны для понимания, особенно если этот программист не знаком с C. Это затрудняет идентификацию для тех, кто занимается этой проблемой ниже по течению, например, в интерпретируемом / JIT-моде. - person tresf; 12.05.2021