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

基於鏈表的 C 語言多人聊天室(Server/Client)完整實現與架構解析

     編輯:關於C

項目背景與演進

從 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() 並通知對方

關鍵數據結構 _Client

typedef 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) 零字節探活,跨平台兼容性好。
  • 線程職責單一:Accept/Recv/Send/Manager 分離,邏輯清晰。

待優化(作者自述 + 專業建議)

  1. 消息持久化:引入 SQLite/MySQL 存離線消息、歷史記錄。
  2. 用戶認證:註冊/登錄,密碼哈希存儲,Token 驗證。
  3. 群聊支持:廣播模式 SendToAll(),或引入房間概念。
  4. 健壯性增強:send/recv 返回值完整處理(粘包/分包)、緩衝區動態擴容、優雅關閉協議。
  5. 跨平台:抽離 Socket 介面,Linux 下用 epoll + 非阻塞 IO 替換多線程,支撐 C10K+。
  6. 內存安全: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 多路復用、協議框架、存儲層、安全體系。

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