#windows #sockets #networking #tcp #network-programming
Вопрос:
Я только что обнаружил, что — в Windows 10 — я могу привязать два сокета к (предположительно) одному и тому же TCP-порту. Хитрость заключается в привязке одного сокета ко всем интерфейсам (0.0.0.0:12345), а другого-к локальному хосту.
Рассмотрим этот фрагмент Python для демонстрации:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(("0.0.0.0", 12345))
s2.bind(("127.0.0.1", 12345))
Windows 10 с радостью принимает эту конфигурацию, в то время как в Linux это не удается Address already in use
.
Я знаю, что сетевые стеки отличаются в этих операционных системах, но я не ожидал этой конкретной проблемы.
Проблема, с которой я сталкиваюсь, заключается в том, что в этом тесте используются некоторые устаревшие продукты, о которых я должен позаботиться, и мне интересно, есть ли способы сделать так, чтобы Windows не допускала эту множественную привязку.
Обновление: я забыл сформулировать свои вопросы:
- Почему это так?
- Есть ли способы изменить такое поведение?
Комментарии:
1. Чтобы избежать такого поведения в Windows, включите параметр
SO_EXCLUSIVEADDRUSE
сокет. Дополнительные сведения см. в разделе Использование SO_REUSEADDR и SO_EXCLUSIVEADDRUSE в MSDN.2. Вау, большое спасибо @RemyLebeau. Я не знал об этом варианте.
s.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1)
действительно решает проблему, представленную здесь.3. Вы должны включить это в ответ, чтобы я мог дать вам кредиты.
4. По причинам, пока мне неизвестным, это не решает мою реальную, более сложную проблему. У меня есть mysqld, работающий на 0.0.0.0:<порт> и <порт>
SO_EXCLUSIVEADDRUSE
в процессе тестирования еще не вызывает сбой. Но это то, над чем я должен сейчас поработать более подробно.5. Не берите в голову. Он работает по назначению. Раньше я не читал всю статью целиком. Я смотрел на таблицу, в которой показано поведение для XP и более ранних версий, но я не видел другой таблицы (в разделе «Повышенная безопасность сокетов»), которая показывает поведение в более новых версиях Windows, которое фактически позволяет вашему сценарию успешно выполнить 2-ю привязку, если обе привязки находятся под одной учетной записью пользователя, но не под разными учетными записями пользователей.