從 1v1 到 1vN,核心痛點在於連接管理效率。初版數組/固定結構導致 CPU 飆升 100%,引入單向鏈表動態管理客戶端節點,CPU 穩定在 20% 以下。純 C 實現無 STL 支持,所有容器、線程同步、網絡收發均手寫,代碼量較大但可控。
| 需求 | 技術方案 | 關鍵數據結構 |
|---|---|---|
| 高並發連接管理 | 鏈表動態增刪,O(1) 頭插,O(n) 遍歷查找/刪除 | _Client 節點含 SOCKET、userName、ChatName、next |
| 指定私聊 | 客戶端維護 ChatName 字段,服務端按名轉發 | ChatName[16] 存儲目標用戶名 |
| 中途切換對象 | 客戶端按 ESC 輸入新名,發送 #新名 指令,服務端解析更新 ChatName | 協議約定:# 為切換標識 |
| 離線通知 | 管理線程定期 send("") 探活,失敗則廣播下線通知並清理節點 | CheckConnection() + 2s 間隔 |
主線程 main()
├─ 初始化 Winsock、創建監聽 Socket、bind/listen
├─ 啟動 Accept 線程 ThreadAccept
│ ├─ 循環 accept() 新連接
│ ├─ 接收 userName、ChatName
│ ├─ 分配 _Client 節點,頭插入鏈表 AddClient()
│ ├─ 連接數 ≥ 2 時啟動 Recv 線程池 StartRecv()
│ └─ 啟動 Manager 線程 ThreadManager(2s 心跳檢測)
├─ Recv 線程池(每客戶端一線程 ThreadRecv)
│ ├─ recv() 讀取數據
│ ├─ 解析 #指令(切換對象)或普通消息
│ ├─ 構造 _Send 結構,啟動 Send 線程 ThreadSend
│ └─ Sleep(200) 降低 CPU 佔用
├─ Send 線程 ThreadSend
│ └─ SendData() 按 ToName 查找 Socket,發送 "From: msg"
└─ Manager 線程 ThreadManager
└─ 遍歷鏈表 send("", 0) 探活,失敗則 RemoveClient() 並通知對方
_Clienttypedef struct _Client {
SOCKET sClient; // 客戶端 Socket
char buf[128]; // 接收緩衝區
char userName[16]; // 自己的用戶名
char IP[20]; // 客戶端 IP
unsigned short Port; // 端口
UINT_PTR flag; // 唯一標識(用 Socket 值)
char ChatName[16]; // 當前聊天目標用戶名
struct _Client *next; // 鏈表指針
} Client, *pClient;
主線程 main() → ConnectServer()
├─ 初始化 Winsock、輸入 Server IP、connect()
├─ 發送 userName、ChatName
├─ 啟動 Recv 線程 ThreadRecv
│ ├─ 循環 recv() 顯示消息
│ └─ 設置 iStatus 供發送線程參考
└─ 啟動 Send 線程 ThreadSend
├─ getch() 非阻塞讀鍵
├─ ESC(27) → 輸入新 ChatName → 發送 "#新名"
├─ 方向鍵(72/80/75/77) → 忽略(避免干擾顯示)
└─ 普通輸入 → 發送消息內容
#name 切換、From: msg 格式,無需複雜序列化。send("", 0) 零字節探活,跨平台兼容性好。SendToAll(),或引入房間概念。send/recv 返回值完整處理(粘包/分包)、緩衝區動態擴容、優雅關閉協議。epoll + 非阻塞 IO 替換多線程,支撐 C10K+。malloc 失敗檢查、strcpy → strncpy、gets_s 替代 gets。// 環境:Windows 10 + VS2015 (MSVC)
// Server
cl Server.cpp ClientLinkList.cpp /link ws2_32.lib
// Client
cl Client.cpp /link ws2_32.lib
// 運行:先啟 Server,再開多個 Client,輸入 Server IP、用戶名、聊天對象
// 局域網互通前提:防火牆放行 18000 端口,雙向 ping 通
這是一個「教學級」但「生產級思維」的 C 語言網絡編程實戰:用鏈表解決動態管理,用多線程解決並發收發,用簡潔協議實現業務邏輯。雖缺乏持久化、認證、擴展性,但核心骨架清晰,極適合作為網絡編程入門項目或輕量級內網通訊原型。進階方向:IO 多路復用、協議框架、存儲層、安全體系。