当服务器有多个网卡时,我们需要指定所有网卡进行监听,以确保能够接收所有连接请求。下面是实现 C# 多网卡 Server Listen 的完整攻略。
第一步:获取本机所有 IP 地址
在 C# 中,可以使用 Dns.GetHostAddresses()
方法获取本机所有的 IP 地址,代码如下:
var hostName = Dns.GetHostName();
var addresses = Dns.GetHostAddresses(hostName);
Dns.GetHostName()
方法返回本地计算机的名称,而 Dns.GetHostAddresses()
方法则返回一个 IPAddress[]
数组,其中包含了计算机所有的 IP 地址。需要注意的是,返回的数组中可能包含 IPv4 和 IPv6 的地址,需要进行筛选。
第二步:创建多个侦听器
接下来,我们需要为每个 IP 地址创建一个 TCP 侦听器。可以使用 TcpListener(IPAddress address, int port)
构造函数创建一个指定 IP 和端口的侦听器。在创建侦听器时,需要指定端口号以及 IP 地址(可以是 IPv4 或 IPv6)。
foreach (var address in addresses)
{
if (!address.IsIPv6LinkLocal && !address.IsIPv6Multicast && !address.IsIPv6SiteLocal)
{
try
{
var listener = new TcpListener(address, port);
listeners.Add(listener);
listener.Start();
Console.WriteLine($"Listening on {address}:{port}");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
}
以上示例代码中,我们遍历计算机中的所有 IP 地址,并判断地址是否为 IPv6 链路本地地址、广播地址或者站点本地地址。如果不是,则创建一个以该地址为绑定地址的 TCP 侦听器,并加入 listeners
列表中。
第三步:监听连接请求
最后一步是监听连接请求。一般情况下,我们会使用异步方式监听连接请求,以充分利用系统资源。下面是一个简单的异步监听代码示例:
while (true)
{
try
{
foreach (var listener in listeners)
{
if (listener.Pending())
{
var client = await listener.AcceptTcpClientAsync();
_ = ProcessAsync(client); // 处理连接请求
}
}
await Task.Delay(10);
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
在上面的代码中,我们首先遍历所有的侦听器,检查是否有连接请求到达。如果有连接请求到达,我们会异步地接受该请求,并调用 ProcessAsync()
方法处理连接请求。为了避免阻塞 CPU,我们加入了 Task.Delay(10)
,使线程睡眠一小段时间后再进行新一轮的轮询。
针对不同的业务需求,ProcessAsync()
方法可能会有所不同。例如,我们可以在该方法中实现对连接请求的数据读取、处理和响应等操作。
示例说明
下面是两个示例,分别介绍如何在 C# 中使用多网卡实现 Server Listen。
示例一:同时监听 IPv4 和 IPv6
我们假设服务器拥有一个以太网网卡和一个 WLAN 网卡。为了同时监听这两个网卡的 IPv4 和 IPv6 地址,我们可以使用以下代码:
var port = 8080;
var listeners = new List<TcpListener>();
var hostName = Dns.GetHostName();
var addresses = Dns.GetHostAddresses(hostName);
foreach (var address in addresses)
{
if (!address.IsIPv6LinkLocal && !address.IsIPv6Multicast && !address.IsIPv6SiteLocal)
{
try
{
var listener = new TcpListener(address, port);
listeners.Add(listener);
listener.Start();
Console.WriteLine($"Listening on {address}:{port}");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
else if (!address.IsIPv4MappedToIPv6 && !address.IsIPv6Multicast && !address.IsIPv6LinkLocal && !address.IsIPv6SiteLocal)
{
try
{
var listener = new TcpListener(address, port);
listeners.Add(listener);
listener.Start();
Console.WriteLine($"Listening on {address}:{port}");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
}
while (true)
{
try
{
foreach (var listener in listeners)
{
if (listener.Pending())
{
var client = await listener.AcceptTcpClientAsync();
_ = ProcessAsync(client); // 处理连接请求
}
}
await Task.Delay(10);
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
在这个示例中,我们首先遍历计算机的所有 IP 地址,判断是否为 IPv4 或 IPv6 地址。如果是 IPv4 地址或 IPv6 非链接本地地址、广播地址或站点本地地址,则创建一个 TCP 侦听器,并监听指定端口。最后使用异步方式监听连接请求,并调用 ProcessAsync()
方法处理请求。
示例二:监听指定网卡
在某些情况下,我们可能只想监听某些特定的网卡。例如,在服务器以太网口和内网口都有连接的情况下,我们只想监听以太网口的连接请求。此时,我们可以通过指定一个网卡的 IP 地址来实现。
假设以太网口的 IP 地址为 192.168.1.100
,我们就可以使用以下代码来监听它的连接请求:
var port = 8080;
var ipAddress = IPAddress.Parse("192.168.1.100");
var listener = new TcpListener(ipAddress, port);
listener.Start();
Console.WriteLine($"Listening on {ipAddress}:{port}");
while (true)
{
try
{
if (listener.Pending())
{
var client = await listener.AcceptTcpClientAsync();
_ = ProcessAsync(client); // 处理连接请求
}
await Task.Delay(10);
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
}
}
在这个示例中,我们直接使用 IPAddress.Parse()
方法将指定的 IP 地址转换为 IPAddress
类型,并创建一个 TCP 侦听器。最后使用异步方式监听连接请求,并调用 ProcessAsync()
方法处理请求。
以上就是实现 C# 多网卡 Server Listen 的完整攻略及两条示例说明。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 多网卡 Server Listen - Python技术站