本系列文章旨在淺顯易懂地介紹 C# 網路程式設計的核心基礎知識。筆者功力有限,僅提供入門級指引,若需深入研究,建議參考專業書籍。本文為系列首篇,重點闡述基於 Socket 的網路程式設計基本概念,涵蓋 TCP 協定、Socket 運作原理、三種主流聊天程式開發模式,以及兩項核心操作:連接埠監聽與遠端伺服器連線。後續文章將逐步實作字串傳輸、非同步通訊、檔案收發,最終完成一個具備線上聊天與檔案傳輸功能的綜合聊天程式。
TCP 屬於傳輸層協定,特性為「面向連線」、「全雙工」、「點對點」以及「可靠傳輸」。所謂面向連線,意指雙方進程必須經過三向交握確認連線成功,才能傳輸實際資料。全雙工意味著連線建立後,資料可雙向流動;點對點則限定一條 TCP 連線僅連結兩個端點;可靠傳輸保證資料有序、無誤到達。
應用程式位於應用層,欲使用 TCP 服務,需透過 Socket 介面。Socket 如同郵筒投遞口:應用層負責撰寫、封裝資料(信件),投入 Socket 後,後續路由、傳輸等細節由底層協定處理,開發者無需關心。Socket 核心包含本地端點(本機 IP 與連接埠)與遠端端點(對方 IP 與連接埠)資訊。


一台電腦同時運行多個網路程式,遠端主機需透過連接埠號辨識目標程式。恰似電話號碼(IP)加分機號(Port),唯有正確組合才能精準送達。
.NET 提供 TcpListener 與 TcpClient 封裝底層 Socket,簡化開發。TcpListener 專責監聽連線請求,TcpClient 則處理資料收發流。監聽端接受請求後,會產生一個 TcpClient 實例進行實際通訊,而 TcpListener 持續保持監聽狀態,可同時服務多個用戶端。

每部電腦同時扮演用戶端與伺服器,需自行監聽連接埠。新節點上線時透過 UDP 廣播宣告存在,其他節點回應確認。缺點是廣播機制複雜,且隨節點增加管理困難。

引入專用伺服器處理節點上線廣播。節點啟動先連線伺服器,伺服器將新節點資訊轉發給所有在線節點,後續節點間直接建立 TCP 連線通訊。各節點仍需維持監聽狀態。

所有訊息經由伺服器中轉:節點 A → 伺服器 → 節點 B。優點在於節點無需監聽連接埠,僅伺服器監聽即可,大幅簡化開發。大型檔案傳輸時可臨時建立點對點連線。伺服器亦可快取離線訊息,實現離線推播。

本系列採用模式三作為最終實作架構。
建立主控台專案 ServerConsole,使用 TcpListener 於本機 IP(127.0.0.1)與連接埠 8500 開始監聽:
using System.Net;
using System.Net.Sockets;
class Server {
static void Main(string[] args) {
Console.WriteLine("Server is running ...");
IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
TcpListener listener = new TcpListener(ip, 8500);
listener.Start();
Console.WriteLine("Start Listening ...");
Console.WriteLine("\n\n按 'Q' 鍵退出。");
ConsoleKey key;
do {
key = Console.ReadKey(true).Key;
} while (key != ConsoleKey.Q);
}
}
執行後可透過 netstat -a 確認連接埠 8500 狀態為 LISTENING。程式必須阻塞(如 Console.ReadKey)避免提前結束導致連線中斷。
建立 ClientConsole 專案,使用 TcpClient.Connect 同步連線:
class Client {
static void Main(string[] args) {
Console.WriteLine("Client Running ...");
TcpClient client = new TcpClient();
try {
client.Connect("localhost", 8500);
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return;
}
Console.WriteLine("Server Connected!{0} --> {1}",
client.Client.LocalEndPoint, client.Client.RemoteEndPoint);
// 按 Q 退出邏輯省略
}
}
連線成功後,用戶端會獲得一個隨機指派的本地連接埠(如 4761),伺服器端 8500 維持監聽狀態,可接受多連線。
迴圈建立多個 TcpClient 實例並各自呼叫 Connect 即可實現多連線。每個實例對應獨立 Socket 與連接埠,伺服器端 8500 持續監聽,netstat -a 可見多組 ESTABLISHED 連線。
呼叫 listener.AcceptTcpClient() 同步阻塞等待連線,獲得 TcpClient 實例後可讀取遠端端點資訊。
將 AcceptTcpClient() 置於 while(true) 迴圈中,每當有新連線即處理並印出資訊。雖為無限迴圈,但方法阻塞特性使其大多數時間處於等待狀態,不會耗盡資源,亦符合伺服器長期運行特性。
本篇結束,下一篇將探討伺服端與用戶端間的資料收發機制。