作者利用寒假 17 天,基於 TCP/IP Socket 多執行緒開發了一套類 QQ 的局域網即時通訊軟體,包含伺服端 NetMsgServer 與客戶端 NetMsgClient,支援多點文字聊天、點對點檔案傳輸、上線/下線即時感知。原始碼 3000+ 行,採用原生 send/recv 而非 CSocket 以追求效能。

NetMsgServer 設計accept() 客戶端連線請求採用完成端口 (IOCP) 或執行緒池 可進一步擴展至千級併發,但本專案採簡單的一連線一執行緒模型,適合中小型區域網。
NetMsgClient 多執行緒架構每個客戶端同時扮演「訊息伺服端」與「訊息客戶端」角色,實現 P2P 多點通訊:
| 執行緒 | 功能 | 埠號 |
|---|---|---|
| 1 | 登入伺服器(發送 USER/PASS) | 4000 |
| 2 | 取得線上名單(LIST 指令) | 4000 |
| 3 | 訊息伺服端 Accept 迴圈 | 4001 |
| 4+ | 每個聊天對象一條接收執行緒 | 4001 |
| N | 檔案傳輸伺服端/客戶端 | 4002 |
// 用戶資料
typedef struct {
long id;
char nickname[20];
char sex[10];
int age;
char address[50];
char password[20];
} USER_INF;
// 線上用戶
typedef struct {
long id;
char nickname[20];
char ip[16];
SOCKET s;
} ONLINEUSER_INF;
// 註冊
"REGT\t\n" + USER_INF 結構體
// 登入
"USER 1000\t\n"
"PASS password\t\n"
// 取得線上名單
"LIST\t\n" -> 回傳 ONLINEUSER_INF 陣列
// 發起聊天
"chat 1001\t\n" -> 對方收到後回覆 ACCEPT_CHAT_REQ / REJECT_CHAT_REQ
// 檔案傳輸
"File xxx.avi\t\n" -> 對方連接檔案埠 4002 開始傳輸
while (TRUE) {
int sockLen = sizeof(inetAddr);
SOCKET sAccept = accept(sListen, (SOCKADDR*)&inetAddr, &sockLen);
if (sAccept == INVALID_SOCKET) { /* 錯誤處理 */ }
AfxBeginThread(ThreadRecvMsgServer, (LPVOID)sAccept);
}
// 接收到 "chat 1001\t\n"
if (目前聊天人數過多) {
send(acceptSocket, "REJECT_CHAT_REQ\t\n", ...);
} else {
send(acceptSocket, "ACCEPT_CHAT_REQ\t\n", ...);
// 建立雙向通訊迴圈
}
NetMsg 完整展示了「客戶端同時作為伺服端」的 P2P 多點通訊架構,對理解即時通訊核心流程、多執行緒 Socket 程式設計極具參考價值。完整原始碼請參考本文配套下載。