Winsock 是 Windows 平台網絡編程的基石。本文提供最精簡的 TCP 服務端/客戶端配對代碼,涵蓋初始化、套接字創建、綁定/連接、收發數據、清理全流程,適合快速上手驗證網絡通信。
// server.cpp #include#include #pragma comment(lib, "ws2_32.lib") void main() { // 1. 初始化 Winsock WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { printf("WSAStartup failed\n"); return; } // 2. 創建套接字 SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (server == INVALID_SOCKET) { printf("socket failed: %ld\n", WSAGetLastError()); WSACleanup(); return; } // 3. 綁定地址端口 sockaddr_in service = {0}; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr("127.0.0.1"); service.sin_port = htons(27015); if (bind(server, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) { printf("bind failed\n"); closesocket(server); WSACleanup(); return; } // 4. 監聽 if (listen(server, 1) == SOCKET_ERROR) { printf("listen failed\n"); closesocket(server); WSACleanup(); return; } // 5. 接受連接 printf("Waiting for client...\n"); SOCKET client = accept(server, NULL, NULL); if (client == INVALID_SOCKET) { printf("accept failed\n"); closesocket(server); WSACleanup(); return; } printf("Client connected.\n"); closesocket(server); // 單連接示例,關閉監聽套接字 // 6. 收發數據 char recvBuf[32] = "", sendBuf[32] = "Server: Sending Data."; int bytesRecv = recv(client, recvBuf, 32, 0); printf("Bytes received: %ld\n", bytesRecv); int bytesSent = send(client, sendBuf, strlen(sendBuf), 0); printf("Bytes sent: %ld\n", bytesSent); closesocket(client); WSACleanup(); }
// client.cpp #include#include #pragma comment(lib, "ws2_32.lib") void main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { printf("WSAStartup failed\n"); return; } SOCKET client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client == INVALID_SOCKET) { printf("socket failed: %ld\n", WSAGetLastError()); WSACleanup(); return; } sockaddr_in serverAddr = {0}; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(27015); if (connect(client, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { printf("connect failed\n"); closesocket(client); WSACleanup(); return; } char sendBuf[32] = "Client: Sending data."; char recvBuf[32] = ""; int bytesSent = send(client, sendBuf, strlen(sendBuf), 0); printf("Bytes sent: %ld\n", bytesSent); int bytesRecv = recv(client, recvBuf, 32, 0); if (bytesRecv > 0) printf("Bytes received: %ld\n", bytesRecv); else if (bytesRecv == 0) printf("Connection closed\n"); else printf("recv failed: %d\n", WSAGetLastError()); closesocket(client); WSACleanup(); }
| 步驟 | 服務端 | 客戶端 |
|---|---|---|
| 1 | WSAStartup | WSAStartup |
| 2 | socket() | socket() |
| 3 | bind() | connect() |
| 4 | listen() | - |
| 5 | accept() | - |
| 6 | recv/send | send/recv |
| 7 | closesocket + WSACleanup | closesocket + WSACleanup |
WSAEADDRINUSE (10048):端口被佔用(TIME_WAIT 狀態),可用 SO_REUSEADDRWSAECONNREFUSED (10061):服務端未啟動/端口錯誤/防火牆攔截WSAETIMEDOUT (10060):連接超時(網絡不通/防火牆/服務端未 accept)WSAECONNRESET (10054):對端強制關閉(RST 包)accept 循環 + CreateThread/_beginthreadex/IOCP/Select 模型ioctlsocket(FIONBIO) / WSAAsyncSelect / WSAEventSelect / IOCP