如何监听多个IP地址?

9
如果我的服务器分配了多个IP地址,并且我想要监听其中一些(或全部),我该怎么做?
我需要为每个IP地址创建一个新的套接字并进行绑定吗?我能够将多个IP地址绑定到单个套接字上吗?IPAddress.Any是否会监听所有IP地址?MSDN库对此事非常不清楚。
6个回答

19

一个单独的socket不能绑定到多个端点,如果你第二次调用Bind()来给特定的socket绑定端点,则会导致SocketException (无效参数错误)。

正如其他人所说,你可以使用IPAddress.Any来监听本地机器上的IPv4地址。但是,如果你只想监听可用IP地址的子集,则必须创建单独的sockets。


6
不,如果仅考虑IP v6地址,IPAddress.Any并不会将Socket对象绑定到所有IP地址上。正确的方法是创建两个Socket对象。然后一个绑定到IPAddress.Any,另一个绑定到IPAddress.IPv6Any。 - Lex Li
1
好的观点。我的项目仍然只支持IPv4,所以当我写下我的答案时,IPv6甚至没有被考虑过。 - Matt Davis
var listener = new TcpListener(IPAddress.IPv6Any, Port); listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0); listener.Start();@LexLi 这将帮助我创建双栈,对吗? - sarat

4

从技术上讲,您的服务器从未分配任何IP地址。

相反,可以为每个网络接口分配IP地址。通常,每个NIC都会获得一个IP地址,但这只是最常见的情况。

如果您想控制哪些接口在所选端口上侦听传入连接,则需要为每个接口创建单独的套接字。


1
是的,我知道你给接口分配IP地址,但是.NET将这个过程隐藏起来,你只需要绑定到端点。不过我有点困惑的是为什么你可以使用“IPAddress.Any”在多个接口上监听,却需要多个套接字来监听特定的接口。 - Erik Funkenbusch
1
我怀疑这是框架设计者的一种“让常见情况易于实现”的方式,提供了一个有用的快捷方式。 - Bevan
任何和IPv6Any都可以被视为快捷方式。但你不能要求框架提供你想要的所有快捷方式。我完全同意Bevan的观点。当你更多地使用框架并开始设计自己的框架时,你会发现做出选择总是很困难的。 - Lex Li
@ErikFunkenbusch 你弄清楚困惑的答案了吗?我也有同样的困惑。 - Zeltrax

3
如果您想监听所有IPv4和IPv6地址,请使用以下代码:
var listener = new TcpListener(IPAddress.IPv6Any, port);
listener.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);

IPv6Any表示Windows将侦听IPv6堆栈。将套接字选项设置为false表示Windows不限制自己只侦听IPv6堆栈,而是还要侦听IPv4堆栈。默认设置是仅在明确指定的堆栈上侦听。


哇,这还真是...呃...不是很明显啊 ;) 我猜这并不能证明一种有选择性地监听多个IP的方法。 - Erik Funkenbusch
这可能对大多数人无关紧要,但是只支持.NET 4或更高版本。 - eAi
我想提一下,使用TcpListener.Create(port)会创建一个双模套接字,支持IPv6和IPv4。 - Blackclaws

3

我曾经尝试过使用IPAddress.Any,但这不是正确的方法,它会绑定到任何适合的IP地址。在我的情况下,我有两张网卡,而且我无法解决问题。后来我尝试添加

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

它运行良好。


2

好的,这很有帮助(Bind方法只是表示框架选择要侦听的地址,这相当模糊)。但是如果我只想侦听分配给计算机的10个IP地址中的5个呢?我需要5个套接字吗?还是可以多次调用Bind()并使用不同的端点? - Erik Funkenbusch
是的,您只能绑定到一个地址,除非您绑定到Any或IPv6Any。 - Lex Li

2
MSDN文库似乎在IPAddress.Any方面存在矛盾。 Bind文档称选择“最合适”的地址,而IPAddress.Any文档则表示使用此常量时套接字必须在所有接口上监听活动。然而,我被告知IPAddress.Any文档是正确的。(由于我的声望不够无法留下评论,因此将其添加为答案)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接