本文提供一套基於 MFC (Microsoft Foundation Classes) 的 UDP 伺服器/客戶端雙向通訊完整實作。採用 CAsyncSocket 衍生類別搭配執行緒監聽,實現無連線、低延遲的訊息收發,適合即時訊息、廣播、遊戲狀態同步等場景。
class CServerView : public CView {
// 通訊相關
SOCKET m_sock; // UDP Socket
HANDLE m_hListenThread; // 監聽執行緒
BOOL m_bInitialized; // Winsock 初始化旗標
SOCKADDR_IN saClnt; int saClntLen; // 客戶端位址
BOOL Isconnect; // 連線狀態
// 訊息緩衝
CString m_data[1000];
int count;
CSize sizeTotal;
BOOL flag;
// 執行緒函數
static UINT WINAPI Listen(LPVOID pParam);
};
CServerView::CServerView() {
WSADATA wsaData;
WSAStartup(0x0101, &wsaData); // 版本 1.1
m_sock = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in sa = {AF_INET, htons(5050), INADDR_ANY};
bind(m_sock, (SOCKADDR*)&sa, sizeof(sa));
m_hListenThread = CreateThread(NULL, 0, Listen, this, 0, &idThread);
}
UINT WINAPI CServerView::Listen(LPVOID pParam) {
CServerView* pView = (CServerView*)pParam;
char msg[2000]; SOCKADDR_IN saClnt; int saClntLen;
while (1) {
saClntLen = sizeof(saClnt);
int n = recvfrom(pView->m_sock, msg, 1024, 0, (SOCKADDR*)&saClnt, &saClntLen);
if (n < 0) continue;
switch (msg[0]) {
case 'A': // 客戶端附著
wsprintf(msg, "A: Client from %s attached\n", inet_ntoa(saClnt.sin_addr));
pView->Isconnect = TRUE; pView->saClnt = saClnt; pView->saClntLen = saClntLen;
sendto(pView->m_sock, msg, 1024, 0, (SOCKADDR*)&saClnt, saClntLen);
break;
case 'D': // 客戶端離脫
wsprintf(msg, "D: Client from %s detached\n", inet_ntoa(saClnt.sin_addr));
pView->Isconnect = FALSE;
sendto(pView->m_sock, msg, 1024, 0, (SOCKADDR*)&saClnt, saClntLen);
break;
case 'R': // 一般訊息
pView->m_data[pView->count++] = msg;
pView->flag = TRUE; pView->InvalidateRect(NULL);
break;
}
}
return 0;
}
'A' 附著封包recvfrom 接收回應與訊息// Server 發送給 Client
wsprintf(msg, "R: %s", userInput);
sendto(m_sock, msg, 1024, 0, (SOCKADDR*)&saClnt, saClntLen);
// Client 發送給 Server (同樣格式)
sendto(m_sock, msg, 1024, 0, (SOCKADDR*)&m_saSrvr, sizeof(m_saSrvr));
wsock32.libServer.exe、Client.exe'A' 附著、'D' 離脫、'R' 訊息CAsyncSocket 封裝替代原生 Socket,簡化非同步通知CList<CString> 避免陣列溢位TerminateThread