在 CWinApp::InitInstance 中呼叫 AfxSocketInit(),或手動:
WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); // 建議使用 2.2 版本 // 程式結束時呼叫 WSACleanup()
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (SOCKADDR*)&addr, sizeof(addr));
listen(s, SOMAXCONN);
SOCKET client = accept(s, (SOCKADDR*)&addr, &len);
send(client, buf, len, 0);
recv(client, buf, len, 0);
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.s_addr = inet_addr("192.168.1.100"); // 伺服器 IP
connect(s, (SOCKADDR*)&addr, sizeof(addr));
send(s, buf, len, 0);
recv(s, buf, len, 0);
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 伺服器綁定任意介面
bind(s, (SOCKADDR*)&addr, sizeof(addr));
// 伺服器接收
recvfrom(s, buf, len, 0, (SOCKADDR*)&from, &fromlen);
// 用戶端發送
sendto(s, buf, len, 0, (SOCKADDR*)&to, sizeof(to));
避免阻塞執行緒,利用視窗訊息驅動網路事件。
// 1. 建立異步 Socket
SOCKET s = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
bind(s, (SOCKADDR*)&addr, sizeof(addr));
// 2. 註冊事件通知
#define UM_SOCK WM_USER + 100
WSAAsyncSelect(s, m_hWnd, UM_SOCK, FD_READ | FD_WRITE | FD_CLOSE);
// 3. 訊息對應表
ON_MESSAGE(UM_SOCK, OnSock)
// 4. 處理函數
void CMyDlg::OnSock(WPARAM wParam, LPARAM lParam) {
switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ:
WSARecvFrom(...); break;
case FD_WRITE: /* 可寫入 */ break;
case FD_CLOSE: /* 連線關閉 */ break;
}
}
recv/accept 應放在工作執行緒,UI 執行緒必須保持響應。WSAGetLastError() 處理 WSAEWOULDBLOCK 等非錯誤狀態。closesocket、WSACleanup。