void CClientDlg::OnConnectSend() {
// 1. 初始化 Winsock
WORD wVer = MAKEWORD(2, 2); // 建議 2.2 版
WSADATA wsaData;
if (WSAStartup(wVer, &wsaData) != 0) {
AfxMessageBox(_T("Winsock 初始化失敗")); return;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
WSACleanup(); AfxMessageBox(_T("Winsock 版本不符")); return;
}
// 2. 建立 Socket
SOCKET sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sClient == INVALID_SOCKET) {
WSACleanup(); AfxMessageBox(_T("Socket 建立失敗")); return;
}
// 3. 可選:綁定本地任意端口(通常 connect 會自動分配,可省略)
sockaddr_in localAddr = {};
localAddr.sin_family = AF_INET;
localAddr.sin_port = 0; // 系統自動分配
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sClient, (sockaddr*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) {
int err = WSAGetLastError();
CString msg; msg.Format(_T("綁定失敗:%d"), err);
AfxMessageBox(msg);
closesocket(sClient); WSACleanup(); return;
}
// 4. 連線伺服器
sockaddr_in srvAddr = {};
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(6000);
srvAddr.sin_addr.s_addr = inet_addr("192.168.0.252");
if (connect(sClient, (sockaddr*)&srvAddr, sizeof(srvAddr)) == SOCKET_ERROR) {
int err = WSAGetLastError();
CString msg; msg.Format(_T("連線失敗:%d"), err);
AfxMessageBox(msg);
closesocket(sClient); WSACleanup(); return;
}
AfxMessageBox(_T("連線成功!"));
// 5. 發送資料
const char* buf = "1234567890123456";
int sent = send(sClient, buf, (int)strlen(buf), 0);
if (sent == SOCKET_ERROR) {
AfxMessageBox(_T("發送失敗"));
}
// 6. 清理
Sleep(3000); // 示例等待,實際應視協議而定
closesocket(sClient);
WSACleanup();
}
| 步驟 | 關鍵 API | 常見錯誤 |
|---|---|---|
| 初始化 | WSAStartup(MAKEWORD(2,2), ...) | 版本檢查失敗、未呼叫 WSACleanup |
| 建 Socket | socket(AF_INET, SOCK_STREAM, 0) | 協議族/型別錯誤 |
| 位址轉換 | htons(port)、htonl(IP)、inet_addr | 位元組序搞反、IP 字串格式錯 |
| 連線 | connect | 防火牆阻擋、IP/Port 錯、伺服器未監聽 |
| 發送 | send | 未檢查回傳值、緩衝區溢位 |
| 關閉 | closesocket + WSACleanup | 資源洩漏、重複清理 |
ioctlsocket(FIONBIO) + select/WSAAsyncSelect/WSAEventSelect;CAsyncSocket / CSocket 簡化訊息迴圈。原文件中 addr.sin_port=0; addr.sin_addr.s_addr=htons(INADDR_ANY) 有誤:
INADDR_ANY 已是網路序,應用 htonl;
bind 參數 sClIEntSock 拼寫錯誤;
send 長度硬編碼 16,建議用 strlen 或變數。以上已在範例中修正。