SocketServer всегда выдает BindException для динамических портов

Определения
Известный порт
Номер порта в диапазоне [0, 1023]
Зарегистрированный порт
Номер порта в диапазоне [1024, 49151]
Динамический порт
Номер порта в диапазоне [49152, 65535]

Я пытаюсь создать объект SocketServer. Когда я разрешаю SocketServer выбирать динамический порт (путем привязки к порту 0), он работает, как и ожидалось. Если я явно укажу зарегистрированный порт, он будет работать как положено. Однако, когда я указываю динамический порт, он всегда выдает BindException с сообщением «Адрес уже используется: JVM_Bind». Верхняя часть трассировки стека для исключения:

at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)

Я использую JDK 1.8u74 на компьютере с Windows 7 Enterprise SP1 x64. Код выглядит следующим образом:

SocketServer createServer(final int port) throws IOException {
    // Create a new socket server
    SocketServer server;
    try {
        // Try to bind to all interfaces
        server = new ServerSocket(port, 1, null);
    } catch (BindException e) {
        // If that fails, try to bind to the primary IP address
        final InetAddress address = InetAddress.getLocalHost();
        server = new ServerSocket(port, 1, address);
    }
    return server;
}

Я также пробовал следующую альтернативу:

SocketServer createServer(final int port) throws IOException {
    // Create a new socket server
    final SocketServer server = new SocketServer();
    server.setReuseAddress(true);
    try {
        // Try to bind to all interfaces
        server.bind(new InetSocketAddress(port), 1);
    } catch (BindException e) {
        // If that fails, try to bind to the primary IP address
        final InetAddress address = InetAddress.getLocalHost();
        server.bind(new InetSocketAddress(address, port), 1);
    }
    return server;
}

Обе эти альтернативы вызывают BindException, когда port является динамическим портом. Я проверил, что все примерно 50 протестированных динамических портов доступны в соответствии с результатами netstat -an. Есть ли способ создать SocketServer для определенного динамического порта?


person Jeff G    schedule 06.04.2016    source источник
comment
Я предлагаю вам отследить значение port. Такой код работает для всех остальных.   -  person user207421    schedule 06.04.2016


Ответы (1)


Хотя это и не идеально, поскольку требует редактирования реестра, есть ответ на ошибку сервера.

Windows может быть настроена на исключение портов из диапазона динамических портов. Просто добавьте диапазон(ы) для исключения в значение Multi-String:

HKLM\System\CurrentControlSet\Services\TCPIP\Parameters\ReservedPorts

Итак, в моем случае у меня есть требование использовать порты 55101-55107, поэтому я добавил этот текст в значение реестра и перезагрузил компьютер. Хотя это решение позволяет мне использовать эти порты, разочаровывает то, что мне приходится редактировать реестр на любом компьютере с Windows, где я хочу их использовать. Кроме того, если в будущем мне придется добавить еще один динамический порт, мне придется повторно редактировать реестр.

person Jeff G    schedule 06.04.2016