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

2 Процессы, прослушивающие один и тот же порт -.NET not throwing exception

На приведенном ниже рисунке показаны 2 процесса, которые пытались и успешно связали сокеты-сокеты (сервер) с портом 10000 на моем локальном компьютере:

Sysinternals showing 2 binds on port 10000

и здесь вывод netstat (для подтверждения):

netstat -a -n | find "10000"
  TCP    0.0.0.0:10000          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:10000          0.0.0.0:0              LISTENING
  TCP    [::]:10000             [::]:0                 LISTENING

(NB: процесс javaw.exe был первым, кто открыл сокет для прослушивания на 10000).

Пока я знаю ситуации, при которых несколько процессов могут прослушиваться на одном и том же порту (SO_REUSEADDR), есть определенные вещи, которые мешают мне в моем конкретном сценарий:

  • В моем приложении я специально говорю .NET, что я хочу эксклюзивное сокет прослушивания (SO_EXCLUSIVEADDRUSE) через

    listener = new TcpListener(adr, ipport);
    listener.ExclusiveAddressUse = true;
    
  • .NET делает not выдачу каких-либо исключений/ошибок/уведомлений о том, что порт уже используется. На самом деле, он на самом деле считает, что все прошло хорошо.

  • Моя серверная программа никогда не просыпается от вызова listener.AcceptTcpClient() с этого момента. Клиентское приложение, которое должно взаимодействовать с сервером, получает действительное соединение, но не может связываться с "моим" сервером (предположительно потому, что оно устанавливает соединение с "другим" процессом, который не говорит о его "протоколе" ).

В случае, если кто-то хочет попытаться воспроизвести мои выводы: Второй процесс - это выпуск Helix для Eclipse (PHP). Но конкретный процесс не должен иметь значения здесь: если один процесс может делать странные вещи под ОС, так что другие могут.

Любые советы о том, как я могу либо получить ошибку, либо вообще предотвратить такую ​​ситуацию (с помощью дополнительных параметров)?

4b9b3361

Ответ 1

Ссылка MSDN, опубликованная в вашем комментарии, кажется, отвечает на ваш вопрос.

Это связано с привязкой Java-приложения к конечной точке подстановочного IP-адреса (0.0.0.0 ip4; :: для ip6 или IPEndpoint.ANY). Я предполагаю, что переменная adr в вашем фрагменте кода выше - это определенный IP-адрес, а не адрес подстановки.

Взгляните на таблицы в этой статье. В нем перечислены результаты попыток привязки к определенной или конечной точке шаблона во второй раз с различными комбинациями параметров сокета.

Короче говоря, код Java является обязательным для конечной точки подстановки 0.0.0.0 без опции сокета SO_EXCLUSIVEADDRUSE. Матрица показывает, что когда это произойдет, вы можете успешно привязать к конкретному адресу и передать запрос на использование исключительного адреса.

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

Ответ 2

Не уверен, почему он не выбрасывает исключение. Хотя, как говорят docs, конструктор TcpListener действительно не проверяет, открыт или нет порт, и поэтому он вызывает только ArgumentException, когда номер порта недействителен. Другие методы, такие как Start, будут бросать SocketException с ErrorCode на WSAEADDRINUSE (10048), когда порт уже открыт другим процессом (см. Метод запуска и Коды ошибок Socket).

Чтобы предотвратить это, вызовите Start и поймайте SocketException или используйте пространство имен System.Net.NetworkInformation для запроса всех используемых портов и выясните, доступен ли определенный порт, как в этом ответе: В С#, как проверить, доступен ли порт TCP?

Ответ 3

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

Ответ 4

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.exclusiveaddressuse.aspx - Обратите внимание на некоторые отличия ОС относительно ExclusiveAddressUse. Попробуйте запустить как администратор. Еще одна мысль, попробуйте войти в Управление компьютерами → Услуги и остановите службу обмена портами Net.Tcp.