前言
在多網卡(多 IP)伺服器環境中,C# 的 TcpListener 需正確指定綁定的本地端點(IP + Port)。本文說明如何使用 IPEndPoint 與 IPAddress.Any 實現「監聽所有介面」或「指定單一介面」的靈活部署策略。
核心概念
| 類別/屬性 | 用途 |
TcpListener | TCP 伺服器監聽器,提供同步阻塞式 AcceptTcpClient/AcceptSocket |
IPEndPoint | 封裝 IP 位址與連接埠,代表網路端點 |
IPAddress.Any | 常數 0.0.0.0,表示綁定所有可用網路介面 |
LocalEndpoint | 實際綁定的端點(若建構時指定 Port=0,系統自動分配可查詢此屬性) |
基本用法:監聽所有介面
using System;
using System.Net;
using System.Net.Sockets;
public class MultiNicServer
{
private TcpListener _listener;
private const int Port = 11000;
public void Start()
{
// 綁定 0.0.0.0:11000(所有介面)
IPAddress ip = IPAddress.Any; // 等同 new IPAddress(new byte[4])
IPEndPoint localEP = new IPEndPoint(ip, Port);
_listener = new TcpListener(localEP);
_listener.Start(); // 開始監聽,預設回log佇列長度 5
Console.WriteLine($"伺服器啟動,監聽 {_listener.LocalEndpoint}");
// 同步阻塞接受迴圈
while (true)
{
TcpClient client = _listener.AcceptTcpClient();
Console.WriteLine($"客戶端連入: {client.Client.RemoteEndPoint}");
// 這裡通常啟動新執行緒或 Task 處理 client
HandleClient(client);
}
}
private void HandleClient(TcpClient client)
{
// 實作通訊協定...
client.Close();
}
public void Stop() => _listener?.Stop();
}
進階:指定特定網卡 IP 監聽
// 取得本機所有 IP 位址
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress addr in host.AddressList)
{
if (addr.AddressFamily == AddressFamily.InterNetwork) // IPv4
Console.WriteLine($"可用 IPv4: {addr}");
}
// 選擇特定 IP(例如 192.168.1.100)
IPAddress specificIp = IPAddress.Parse("192.168.1.100");
IPEndPoint ep = new IPEndPoint(specificIp, Port);
_listener = new TcpListener(ep);
非同步模式(.NET 4.5+ 推薦)
public async Task StartAsync(CancellationToken ct = default)
{
_listener = new TcpListener(IPAddress.Any, Port);
_listener.Start();
while (!ct.IsCancellationRequested)
{
TcpClient client = await _listener.AcceptTcpClientAsync();
_ = Task.Run(() => HandleClient(client), ct); // 火燒忘記或加入追蹤集合
}
}
多網卡部署檢查清單
- ✅ 確認防火牆開放目標 Port(所有介面或特定介面)。
- ✅ 使用
netstat -an | findstr :11000 驗證監聽狀態(應顯示 0.0.0.0:11000 或特定 IP)。
- ✅ 若需支援 IPv6,建立雙
TcpListener 分別綁定 IPAddress.IPv6Any。
- ✅ 生產環境建議啟用
SocketOptionName.ReuseAddress 避免重啟時 TIME_WAIT 延遲。
常見錯誤與解決
| 錯誤 | 原因 | 解決 |
SocketException: 要求的地址無效 | 指定的 IP 不屬於本機任何介面 | 改用 IPAddress.Any 或確認 IP 正確性 |
Address already in use | Port 已被其他程序佔用 | 更換 Port 或啟用 ReuseAddress |
| 只能在單一網卡收到封包 | 綁定特定 IP 而非 Any | 改用 IPAddress.Any 監聽所有介面 |
補充:取得實際綁定端點資訊
// 若建構時 Port=0,系統自動分配
var listener = new TcpListener(IPAddress.Any, 0);
listener.Start();
IPEndPoint actual = (IPEndPoint)listener.LocalEndpoint;
Console.WriteLine($"實際綁定: {actual.Address}:{actual.Port}");
- 上一篇文章: C# 遞歸列舉目錄下所有檔案的工具類別實作
- 下一篇文章: 走進 C#(三):語言演進脈絡、核心特性與編譯器入門
Copyright ©
程式碼之家 All Rights Reserved