在这篇博客中,我们将介绍如何使用 Winsock API 在 Windows 上实现简单的 TCP 服务器和客户端。Winsock 是 Windows 套接字扩展,提供了网络编程所需的 API。通过这两个示例代码,我们将展示如何初始化 Winsock 库、创建套接字、进行连接以及发送和接收数据。
首先,我们来看一下服务器端的实现:
#include #include #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { // 初始化套接字库 WORD mVersion; WSADATA wsaData; int err; mVersion = MAKEWORD(1, 1); // 版本 1.1 err = WSAStartup(mVersion, &wsaData); if (err != 0) { return err; } // 检查版本 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } // 创建套接字 SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); if (sockSrv == INVALID_SOCKET) { WSACleanup(); return 1; } // 准备绑定信息 SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); // 绑定套接字 if (bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(addrSrv)) == SOCKET_ERROR) { closesocket(sockSrv); WSACleanup(); return 1; } // 监听端口 if (listen(sockSrv, 10) == SOCKET_ERROR) { closesocket(sockSrv); WSACleanup(); return 1; } cout << "Server started at port 6000" << endl; SOCKADDR_IN addrCli; int len = sizeof(addrCli); char recvBuf[100]; char sendBuf[100]; while (true) { // 接受客户端连接 SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli, &len); if (sockConn == INVALID_SOCKET) { continue; } sprintf_s(sendBuf, "Server send something"); send(sockConn, sendBuf, strlen(sendBuf) + 1, 0); recv(sockConn, recvBuf, sizeof(recvBuf), 0); cout << recvBuf << endl; // 关闭客户端套接字 closesocket(sockConn); } // 关闭服务器套接字并清理库 closesocket(sockSrv); WSACleanup(); system("pause"); return 0; } 初始化 Winsock 库:
WSAStartup 函数初始化 Winsock 库,并请求版本 1.1。创建套接字:
socket 函数创建一个 TCP 套接字。绑定和监听:
bind 函数将套接字绑定到本地地址和端口。listen 函数使套接字进入监听模式,准备接收连接请求。接受连接并处理数据:
accept 函数等待客户端连接请求。send 和 recv 函数进行通信。清理资源:
closesocket 关闭套接字。WSACleanup 清理 Winsock 库。接下来是客户端的实现:
#include #include #pragma comment(lib,"ws2_32.lib") using namespace std; int main() { // 初始化套接字库 WORD mVersion; WSADATA wsaData; int err; mVersion = MAKEWORD(1, 1); // 版本 1.1 err = WSAStartup(mVersion, &wsaData); if (err != 0) { return err; } // 检查版本 if (LOBYTE(mVersion, wsaData) != 1 || HIBYTE(mVersion, wsaData) != 1) { WSACleanup(); return -1; } // 创建 TCP 套接字 SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_port = htons(6000); addrSrv.sin_family = AF_INET; // 连接服务器 connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char sendBuf[] = "Cli send ..."; char recvBuf[100]; // 发送数据到服务器 send(sockCli, sendBuf, strlen(sendBuf) + 1, 0); // 接收服务器发送的数据 recv(sockCli, recvBuf, sizeof(recvBuf), 0); cout << recvBuf << endl; // 关闭套接字并清理库 closesocket(sockCli); WSACleanup(); system("pause"); return 0; } 初始化 Winsock 库:
WSAStartup 函数初始化 Winsock 库,并请求版本 1.1。创建套接字:
socket 函数创建一个 TCP 套接字。连接服务器:
connect 函数连接到指定 IP 地址和端口的服务器。发送和接收数据:
send 函数向服务器发送数据。recv 函数接收服务器发送的数据。清理资源:
closesocket 关闭套接字。WSACleanup 清理 Winsock 库。通过上述示例,我们了解了如何在 Windows 平台上使用 Winsock API 实现基本的 TCP 服务器和客户端。关键步骤包括初始化 Winsock 库、创建套接字、绑定和监听、连接服务器以及数据通信。虽然这些示例较为基础,但它们提供了构建更复杂网络应用程序的基础。希望这篇博客对你理解 Winsock 编程有所帮助。