首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作 TCP 聊天程式:從 Socket 程式設計到 WinForms 完整範例

     編輯:關於C語言

前言

在 .NET Framework 早期,System.Net.Sockets 命名空間提供了低階的 Socket API,讓開發者能直接操作 TCP/UDP 通訊。這篇文章將帶你完整走過一個跨平台(當時指 Windows 9x/NT)的點對點文字聊天程式實作,涵蓋命令列參數解析、非同步 Socket 連線、自訂封包協定、WinForms UI 與事件驅動架構。雖然現代開發慣用 SignalR、gRPC 或 WebSocket,但理解底層 Socket 運作仍是網路程式設計的基石。

專案架構概覽

整個程式僅包含單一 Wintalk.cs 檔案,卻完整實作了三大核心類別:

  • App:進入點,負責解析命令列參數(/L 監聽、/C 連線)、啟動 Talker 與 TalkForm。
  • TalkForm:繼承 Form 的 UI 類別,包含訊息顯示區、輸入區、狀態列,並訂閱 Talker 的事件通知。
  • Talker:實作 IDisposable 的通訊核心,封裝 Socket、StreamReader/Writer、自訂協定(R{長度}:{內容} 全量更新、〈A{長度}:{內容}〉增量更新)、背景執行緒接收迴圈與事件回呼機制。

關鍵技術細節解析

1. 命令列參數與雙模式啟動

// 無參數時預設為 Server,監聽 5150 埠
// /L [port]  指定監聽埠
// /C [address] [port]  指定連線目標

ParseArgs 使用 Dns.Resolve 解析主機名稱,支援 IPv4。若監聽埠被佔用(錯誤碼 10048),會自動切換為 Client 模式連回本機,這是一個有趣的「自動配對」設計。

2. 自訂文字傳輸協定

為了在單一 TCP 連線上可靠傳送可變長度文字,Talker.SendTalk 設計了簡單協定:

  • 全量替換:R{length}:{text} — 當輸入內容非單純追加時使用。
  • 增量追加:A{length}:{text} — 僅傳送新增字元,減少頻寬。

接收端 ReceiveTalk 以狀態機逐字元解析,支援多字節字元(Big5/GB2312 環境下中文字佔 2 位元組),並透過 NotificationCallback 將完整訊息推送給 UI 執行緒。

3. 事件驅動與執行緒安全

// Talker 定義事件
public event NotificationCallback Notifications;

// TalkForm 訂閱並處理
talker.Notifications += HandleTalkerNotifications;

// UI 更新需在 UI 執行緒,但此範例直接在背景執行緒存取控制項
// 現代寫法應搭配 Control.Invoke/BeginInvoke

範例直接在背景執行緒更新 TextBox,在 .NET 1.x/2.0 可能因 CheckForIllegalCrossThreadCalls = false 預設關閉而運作,但在現代 .NET 必須改用 Invoke 或 SynchronizationContext。

4. 資源釋放模式

Talker 實作 IDisposable 並搭配終結子(~Talker),確保 Socket、StreamReader、StreamWriter 正確關閉,避免連線殘留。

完整程式碼重構建議

若要在 .NET 6+ 環境運行,建議進行下列現代化調整:

  1. 將 ThreadPool.QueueUserWorkItem 改為 Task.Run 或 async/await 配合 NetworkStream.ReadAsync。
  2. 使用 CancellationToken 控制接收迴圈結束,取代例外處理流程。
  3. UI 更新統一透過 Invoke 或 Progress<T> 執行。
  4. 編碼統一改為 UTF-8(Encoding.UTF8),避免跨平台亂碼。
  5. 加入單元測試驗證封包編解碼邏輯。

執行方式

// 終端機 1(Server)
dotnet run -- /L 5150

// 終端機 2(Client)
dotnet run -- /C 127.0.0.1 5150

兩視窗啟動後,下方輸入框鍵入文字即時雙向傳送,上方唯讀區顯示對方訊息,狀態列顯示 Listening / Connected。

總結

這個範例雖然年代久遠,但完整展示了:

  • 同步阻塞 Socket 的基本操作流程(Bind → Listen → Accept / Connect)
  • 應用層協定設計(長度前綴 + 指令碼)
  • 事件解耦合通訊邏輯與 UI
  • 資源管理與例外處理

理解這些基礎,對後續學習高階網路框架(Kestrel、gRPC、WebSocket)大有裨益。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved