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

Зарезервировать порт TCP в Windows

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

Как процесс может зарезервировать порт без фактического привязки/прослушивания, а затем безопасно (т.е. избегая условий гонки) передать его другому процессу по запросу?

Номер порта не обязательно должен быть определен заранее. Это нормально, чтобы первый процесс приобрел случайный номер порта и передал его процессу запроса.

EDIT: Мне кажется, что мой вопрос несколько плохо сформулирован. Я действительно хочу отделить выделение номера динамического порта от операции привязки к порту-ноль. Это означает, что вы не просто избегаете случайного случайного распределения этого номера порта, но также предотвращаете привязку любого другого процесса к одному и тому же адресу/порту в промежуточный период. Или, говоря другим способом, я хочу, чтобы один процесс запустил операцию привязки к порту-ноль - сразу же узнав номер порта, который будет использоваться, и пусть назначенный второй процесс завершит операцию привязки в будущем.

В настоящий момент самое близкое взаимодействие, о котором я могу думать, заключается в том, что первый процесс сразу связывается с адресом /0 и остается связанным до тех пор, пока второй процесс не запросит его, и в этот момент он отсоединяет и сообщает другому процессу номер порта, который он приобрел, который затем привязывается к адресу/порту явно. У этого есть две проблемы: 1) я бы предпочел не связываться вообще до тех пор, пока не будет второй процесс; 2) существует небольшой промежуток времени, в течение которого третья сторона может случайно (или намеренно) узурпировать порт.

Фон

Вам может быть интересно узнать, почему я хочу сделать что-то такое странное. Я работал с ZeroMQ, и одним из основных ограничений является отсутствие транспорта ipc:// в Windows. Мне показалось, что процесс сопоставления портов (аналогичный RPC endpoint mapper или Erlang epmd) будет всего лишь билетом для реализации обхода с использованием транспорта tcp:// с динамическими распределениями портов. Тем не менее, клиентам и серверам ZeroMQ разрешено подключаться не по порядку (т.е. Это не ошибка для подключения клиента до привязки сервера), поэтому я пытаюсь выяснить, как можно обнаружить подключающийся клиент - с очень высокая степень достоверности - порт, который будет использоваться для связи, до того, как сервер действительно свяжется с этим портом.

4b9b3361

Ответ 1

Использование команды netsh может помочь вам. Вы можете изменить диапазон динамического порта, используемый Windows.
Это похоже на изменение реестра, которое вы указали, но оно действует немедленно.

см. http://support.microsoft.com/kb/929851 для получения дополнительной информации о команде netsh.

Ответ 2

Как упоминалось в @vahapt, вы можете изменить диапазон динамических портов с помощью netsh.

Однако лучшим решением может быть использование netsh для резервирования портов, требуемых вашим приложением, оставив по умолчанию диапазон динамических портов по умолчанию.

Для этого:

  • На сервере 2008/2008 R2 установите это исправление Microsoft. Это не требуется на сервере 2012 года или позже.
  • Остановить любые процессы, используя зарезервированные порты. Если процесс использует порт, включенный в диапазон портов для резервирования, NETSH вернет следующую ошибку, и резервирование не будет выполнено:

    Процесс не может получить доступ к файлу, потому что он используется другим процессом.

  • Используйте следующую команду NETSH для резервирования портов:

    netsh int <ipv4|ipv6> Add excludedportrange [protocol=]tcp|udp [startport=]<integer> [numberofports=]<integer> [[store=]active|persistent]

    Например, чтобы зарезервировать порты 55368-55372 для UDPv6, используйте команду:

    netsh int ipv6 add excludedportrange protocol=udp startport=55368 numberofports=5

Примечания:

  • По умолчанию резервирование портов сохраняется при перезагрузках
  • Порты могут быть зарезервированы для версий 4 или 6 протокола, но не для обоих (т.е. вы не можете зарезервировать порт 60000 для TCPv4 и TCPv6)

Для получения дополнительной информации см. https://support.microsoft.com/en-us/kb/929851, в том числе о том, как просматривать или удалять существующие резервирования портов.

Ответ 3

Изменить: это относится только к pre-Windows Server 2008 (Microsoft Support KB)

Вы можете отредактировать параметр реестра ReservedPorts в

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

Чтобы зарезервировать ряд портов, следуйте форматам "4000-4010" или "xxxx-yyyy", однако для резервирования одного порта вы должны использовать формат "4000-4000" или "xxxx-xxxx"

http://support.microsoft.com/kb/812873

Ответ 4

Я придумал возможное решение, поэтому я подумал, что могу записать его здесь как ответ.

Процесс может передать сокет другому процессу посредством вызова WSADuplicateSocket, поэтому процесс координации может связываться с динамическим портом и внутренне связывать его с данным именем IPC. Когда приходит процесс сервера ZMQ, который хочет "привязать" к этому имени, координирующий процесс копирует связанный сокет в серверный процесс и закрывает его собственную копию.

Это решение не относится к моим предпочтениям, чтобы избежать вызова bind(), но это может быть не обязательно; Мне нужно будет выполнить некоторые тесты.

Ответ 5

Для ZeromMQ вы можете использовать модуль zbeacon czmq или С# NetMq для реализации обнаружения службы.