2009-11-22 6 views
6

Если у моего сервера несколько назначенных ему IP-адресов, и я хотел бы прослушать некоторые (или все) из них, как мне это сделать?Как прослушивать несколько IP-адресов?

Нужно ли создавать новый сокет для каждого IP-адреса и связывать его? Можно ли связать несколько IP-адресов с одним сокетом? Поддерживает ли IPAddress.Any все IP-адреса? Библиотека MSDN очень неясна в этом вопросе.

ответ

13

Вы не можете связать один сокет с несколькими конечными точками. A SocketException (неверная ошибка аргумента) происходит во второй раз, когда вы вызываете Bind() для данного сокета.

Как уже говорилось, вы можете использовать IPAddress.Any для прослушивания адресов IPv4 на локальном компьютере. Однако, если вы хотите слушать только подмножество доступных IP-адресов, вам придется создавать отдельные сокеты.

+0

Хорошо, спасибо за окончательный ответ. –

+5

Нет, IPAddress.Any не связывает объекты Socket со всеми IP-адресами, если вы просто подсчитываете адреса IP v6. Правильный способ - создать два объекта Socket. Затем один привязывается к IPAddress.Any, а другой привязывается к IPAddress.IPv6Any. –

+0

Хорошая точка. Мой проект по-прежнему является единственным IPv4, поэтому IPv6 даже не был рассмотрен, когда я написал свой ответ. –

2

Да, IPAddress.Any будет прослушивать все интерфейсы.

http://msdn.microsoft.com/en-us/library/system.net.ipaddress.any.aspx

+0

Хорошо, это помогает (метод Bind просто говорит, что структура выбирает адрес для прослушивания, что довольно неопределенно). Но как насчет того, хочу ли я слушать только 5 из 10 IP-адресов, назначенных компьютеру? Нужно ли мне 5 сокетов? или я могу несколько раз называть Bind() несколькими конечными точками? –

+0

Да, вы по одному адресу, если вы не привязаны к Any или IPv6Any. –

4

Технически, ваш сервер никогда не имеет какой-либо IP-адреса, назначенный ему.

Вместо этого отдельным сетевым интерфейсам могут быть назначены IP-адреса. Обычно каждый сетевой адаптер получает один IP-адрес, но это самый распространенный случай.

Если вы хотите контролировать, какие интерфейсы прослушивают входящие соединения на выбранном вами порту, вам нужно создать отдельный сокет для каждого из них.

+1

Да, я знаю, что вы назначаете IP-адреса интерфейсам, но .NET скрывает это от вас, и вы просто привязываетесь к конечным точкам. Я немного смущен, почему вы можете прослушивать Mulitple интерфейсы с помощью IPAddress.Any, но вам нужно несколько сокетов для прослушивания определенных. –

+1

Я подозреваю, что это случай «давайте сделаем простой случай легким для достижения» дизайнерами рамки, предоставляя полезный ярлык. – Bevan

+0

Любые и IPv6Any могут считаться ярлыками. Но вы не можете просить фреймворк предоставить вам все ярлыки, которые вы хотите. Я полностью согласен с Беваном. Когда вы играете больше с фреймворками, и вы начинаете создавать свои собственные, вы увидите, что всегда трудно сделать выбор. –

2

Библиотека MSDN кажется противоречивой относительно IPAddress.Any. Bind док

http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.bind.aspx

говорит, что «наиболее подходящий» адрес выбран, но IPAddress.Any док

http://msdn.microsoft.com/en-us/library/system.net.ipaddress.any.aspx

говорит, что с этой константой сокет должен слушать активности на все интерфейсы.

Однако мне говорят, что это IPAddress.Any doc, это правильно.

(добавив это как ответ, так как у меня недостаточно комментариев, чтобы оставлять комментарии).

3

Я работал над этим, IPAddress.Any не является правильным способом, он свяжет любой подходящий IP-адрес. В моем случае у меня есть 2 NIC, и я не мог решить проблему. Когда я добавил

System.Net.IPAddress ipAddress = IPAddress.Parse("xxx.xxx.xxx.xxx"); 
listener = new TcpListener(ipAddress, portNum); 

Он работал нормально.

3

Если вы хотите слушать все адреса IPv4 и IPv6, используйте этот код:

var listener = new TcpListener(IPAddress.IPv6Any, port); 
listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); 

IPv6Any сообщает Windows, чтобы слушать на стек IPv6. Установка параметра socket в false означает, что Windows не ограничивается стеком IPv6, а скорее также прослушивает стек IPv4. По умолчанию используется только прослушивание в указанном стеке.

+0

Ничего себе, это довольно ... ummm .. неочевидно;) Я предполагаю, что это не доказывает способ прослушивания нескольких IP выборочно. –

+0

Это может не иметь значения для большинства людей, но это поддерживается только в .NET 4 или новее. – eAi

Смежные вопросы