阅读量:4
使用 Winsock 实现 TCP 服务器和客户端
在这篇博客中,我们将介绍如何使用 Winsock API 在 Windows 上实现简单的 TCP 服务器和客户端。Winsock 是 Windows 套接字扩展,提供了网络编程所需的 API。通过这两个示例代码,我们将展示如何初始化 Winsock 库、创建套接字、进行连接以及发送和接收数据。
服务器代码详解
首先,我们来看一下服务器端的实现:
#include<iostream> #include<WinSock2.h> #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<iostream> #include<WinSock2.h> #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 编程有所帮助。