Связывание несколько раз с одним и тем же портом?

Почему следующий код не генерирует исключение "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 не повлияет на привязку. Это влияет только на некоторые особенности того, какие соединения отклоняются или принимаются.

В качестве дополнительного примечания - какой смысл ждать триста миллионов лет?

Другие вопросы по тегам