Связывание несколько раз с одним и тем же портом?
Почему следующий код не генерирует исключение "java.net.BindException: Address уже используется: JVM_Bind"?
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class Test
{
public static void main(String[] args) throws Exception
{
try (ServerSocket socket1 = new ServerSocket();
ServerSocket socket2 = new ServerSocket();
ServerSocket socket3 = new ServerSocket())
{
int port = 10000;
socket1.setReuseAddress(false);
socket1.bind(new InetSocketAddress("0.0.0.0", port));
socket2.setReuseAddress(false);
socket2.bind(new InetSocketAddress("127.0.0.1", port));
socket3.setReuseAddress(false);
socket3.bind(new InetSocketAddress("127.0.0.2", port));
Thread.sleep(Long.MAX_VALUE);
}
}
}
Запуск 'netstat' впоследствии отображает:
C: \ Users \ Администратор>netstat -a -n | findstr 10000 TCP 0.0.0.0:10000 0.0.0.0:0 СЛУШАТЬ TCP 127.0.0.1:10000 0.0.0.0:0 СЛУШАТЬ TCP 127.0.0.2:10000 0.0.0.0:0 СЛУШАТЬ TCP [::]:10000 [::]:0 СЛУШАТЬ
Я запускаю это на Windows Server 2008 R2 (64-разрядная версия), и в "ipconfig /all" отображается только один сетевой адаптер / интерфейс (другие сетевые адаптеры отключены). Но на некоторых других машинах эта программа действительно выдает ожидаемое "java.net.BindException: Адрес уже используется: JVM_Bind"!
Что может происходить?
1 ответ
Вы можете привязать один и тот же номер порта к разным IP-адресам. Операционная система может различать входящие пакеты по их целевому IP-адресу, а также по номеру порта TCP.
В операционной системе нет проблем с сохранением отдельного ServerSocket для 127.0.0.1:1000
а также 127.0.0.2:1000
, Он знает, где принадлежит каждый пакет - даже если он открывает новое соединение.
Обратите внимание, что IP-адрес 0.0.0.0
это просто - IP-адрес (это не действительный IP-адрес в том смысле, что IP-пакеты могут быть отправлены туда, но я не могу поддержать 0.0.0.0 == any
или). Если вы хотите прослушать все адреса, поставьте null
вместо InetSocketAddress. В этот момент у вас больше шансов получить желаемое исключение (если только ОС не решит, что прослушивания с подстановочными знаками имеют более низкий приоритет и в действительности не перекрывают определенные прослушивания, поэтому они могут связывать оба).
Также обратите внимание, что настройка setReuseAddress
не повлияет на привязку. Это влияет только на некоторые особенности того, какие соединения отклоняются или принимаются.
В качестве дополнительного примечания - какой смысл ждать триста миллионов лет?