.NET 網路分層架構
- 請求/回應層:
WebRequest/WebResponse (HTTP、FTP)
- 應用協定層:
TcpClient/TcpListener, UdpClient
- 傳輸層 (Socket):
System.Net.Sockets.Socket,最底層控制,支援同步/非同步、TCP/UDP、原始通訊協定。
Socket 核心類別與方法
| 類別/方法 | 用途 |
Socket(AddressFamily, SocketType, ProtocolType) | 建立 Socket 實例 |
Connect / BeginConnect | 客戶端連線 (同步/非同步) |
Bind / Listen / Accept / BeginAccept | 伺服器綁定、監聽、接受連線 |
Send / Receive / SendTo / ReceiveFrom | 資料收發 (同步) |
BeginSend / BeginReceive | 非同步收發 (APM 模式) |
Shutdown / Close | 關閉連線釋放資源 |
IPEndPoint | IP 位址 + 埠號 組合 |
建立 Socket 範例
// TCP Client
var tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// UDP Socket
var udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
同步 TCP 客戶端:HTTP 下載完整實作
public static void DownloadPage(string host, int port, string savePath)
{
// 1. 解析主機位址
IPHostEntry hostEntry = Dns.GetHostEntry(host);
IPAddress ip = hostEntry.AddressList.First(a => a.AddressFamily == AddressFamily.InterNetwork);
var endPoint = new IPEndPoint(ip, port);
// 2. 建立並連線
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Connect(endPoint);
// 3. 發送 HTTP GET 請求
string request = $"GET / HTTP/1.1\r\nHost: {host}\r\nConnection: Close\r\n\r\n";
byte[] reqBytes = Encoding.ASCII.GetBytes(request);
socket.Send(reqBytes);
// 4. 接收回應 (迴圈讀取直到 0 位元組)
using (var ms = new MemoryStream())
{
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = socket.Receive(buffer)) > 0)
{
ms.Write(buffer, 0, bytesRead);
}
// 5. 儲存檔案
File.WriteAllBytes(savePath, ms.ToArray());
}
socket.Shutdown(SocketShutdown.Both);
}
}
非同步模式 (APM) 關鍵點
- 使用
BeginConnect/EndConnect, BeginSend/EndSend, BeginReceive/EndReceive。
- 需傳遞
AsyncCallback 與狀態物件 (SocketAsyncEventArgs 或自訂類別)。
- 非同步不阻塞執行緒,適合高併發伺服器。
- .NET Core / 5+ 建議使用
Task-based (ConnectAsync, ReceiveAsync) 或 System.Net.Sockets.SocketAsyncEventArgs 高效能模式。
常見異常處理
SocketException:作業系統層級錯誤 (連線拒絕、逾時、網路不可達)。
ObjectDisposedException:對已關閉 Socket 操作。
ArgumentNullException:參數為 null。
最佳實踐
- 優先使用高層 API (
HttpClient, TcpClient) ,除非需要自訂協定/效能極致。
- 使用
using 確保 Socket 釋放。
- 緩衝區大小建議 4K-64K,避免過大造成 LOH 壓力。
- 非同步伺服器端採用
SocketAsyncEventArgs 減少記憶體分配。
- 設定
Socket.NoDelay = true (關閉 Nagle 演算法) 適用於即時性要求高的小封包場景。