本文為系列第四部分,聚焦通訊伺服器的多執行緒設計與用戶端架構要點。
每個客戶端連線成功,伺服器建立兩條執行緒:
雙執行緒同步生成、同步結束。資料轉發邏輯簡化,但連線數受限於伺服器軟硬體能力。
定義 CMutex m_mutex,使用 Lock()/Unlock() 保護共享結構 info_data。
UINT RecvData(void* pParam) {
SOCKET clientSocket = (SOCKET)pParam;
while (true) {
int nRcv = recv(clientSocket, buffer, MAXBUFLEN, 0);
buffer[nRcv] = '\0';
if (strcmp(buffer, "Close!") != 0) { // 非關閉指令
// 尋找目標用戶 (依暱稱)
POSITION pos = s_info.GetHeadPosition();
while (pos) {
USER_INFO info = s_info.GetNext(pos);
if (info.petName == targetName) {
m_mutex.Lock();
info_data.data = buffer;
info_data.thread = info.pThread;
m_mutex.Unlock();
info.pThread->ResumeThread(); // 喚醒對應發送執行緒
break;
}
}
} else { // 收到關閉指令
// 清理用戶資訊、關閉連線、結束執行緒
m_mutex.Lock();
info_data.data = buffer;
m_mutex.Unlock();
pThread->ResumeThread();
s_info.RemoveAt(pos);
break;
}
}
closesocket(clientSocket);
AfxEndThread(0, true);
return 1;
}
UINT SendData(void* pParam) {
SOCKET clientSocket = (SOCKET)pParam;
while (true) {
if (info_data.data != "Close!") {
m_mutex.Lock();
int nSnd = send(clientSocket, info_data.data, info_data.data.GetLength(), 0);
CWinThread* pTargetThread = info_data.thread;
m_mutex.Unlock();
pTargetThread->SuspendThread(); // 自身掛起等待下次喚醒
} else {
break;
}
}
closesocket(clientSocket);
AfxEndThread(0, true);
return 1;
}
已於實驗室區域網路 (1 台伺服器 + 20 台客戶端) 實測通過。
作者:袁淵 (華東船舶工業學院 機械系)