Почему я должен ждать isBound при выделении случайного сокета в Java?
Недавно у меня возникла проблема с библиотекой embedded-postgres . Пытался вручную выбрать свободный порт через
new ServerSocket(0).getLocalPort()
но я где-то попадал в состояние гонки (мои тесты зависли при запуске второго набора тестов).
Затем я узнал, что сама библиотека имеет эту возможность (использовать случайный порт) и не имеет той проблемы, которая была у меня. Я проанализировал исходный код и обнаружил единственную разницу в том, что они проводят дополнительную проверку:
try (ServerSocket socket = new ServerSocket(0)) {
while(!socket.isBound()) {
Thread.sleep(50);
}
return socket.getLocalPort();
}
Поэтому после того, как порт был рандомизирован, они ждут, пока он не будет привязан. Код, о котором я говорю.
Хотелось бы знать, зачем там этот код. В моем понимании «привязка» заключалась в том, что она равносильна «прослушиванию» данного порта, но здесь этого не может быть, поскольку этот код выполняется до запуска сервера. Фактически, сервер запустится (и свяжется) именно с этим портом. Это меня очень смущает.
1 ответ
Код в библиотеке - это исправление этой проблемы, причина которой:
.. похоже, что метод EmbeddedPostgres#detectPort может вызвать проблему, поскольку он не ожидает привязки сокета перед запросом порта, что приводит к тому, что ServerSocket # getLocalPort возвращает -1, как описано в документации.
Таким образом, вызов ServerSocket.getLocalPort() возвращает
-1
если сокет не привязан, и, по- видимому, это может произойти через некоторое время после вызова, хотя неясно, при каких обстоятельствах. Таким образом, код просто ждет, чтобы убедиться, что он привязан.
Однако в документации нигде не сказано, что
new ServerSocket(0)
не возвращает связанный сокет. В javadoc для ServerSocket(int port) говорится: «Создает сокет сервера, привязанный к указанному порту».
Однако у них была проблема, это единственное исправление , и я полагаю, это решило проблему ... так что просто очень непонятная документация в JDK?
Что касается привязки и прослушивания. Привязка - это часть, в которой вы назначаете адрес и порт, она все еще должна активно начать принимать соединения.