VC++实现++tcp网络通讯服务器+客户端(附带源码)
VC++ 实现 TCP 网络通信(服务器 + 客户端)
本文将展示如何使用 VC++ 实现一个简单的 TCP 网络通信应用,包括服务器端和客户端。服务器端负责监听客户端请求并返回数据,而客户端向服务器发送请求并接收响应。
我们将使用 Windows API 中的 Winsock
库来实现网络通信。Winsock 是 Windows 平台上的网络编程接口,支持 TCP/IP 网络通信协议。
项目介绍
本项目的目标是通过使用 Winsock 编写一个简单的 TCP 服务器和客户端。服务器端监听特定的端口,等待客户端连接。客户端连接到服务器并发送请求,服务器返回响应。我们将用 send()
和 recv()
函数来发送和接收数据。
相关知识
-
Winsock 编程:
WSAStartup
:初始化 Winsock 库。socket
:创建一个套接字。bind
:绑定套接字到本地地址和端口。listen
:使套接字处于监听状态。accept
:接受客户端的连接。send
和recv
:发送和接收数据。closesocket
:关闭套接字。WSACleanup
:清理 Winsock。
-
TCP 和 UDP:
- 本项目使用的是 TCP 协议,确保数据传输可靠并按顺序到达。
代码结构
-
服务器端:
- 初始化 Winsock 库。
- 创建套接字并绑定到本地 IP 地址和端口。
- 监听客户端的连接请求。
- 接受客户端连接并进行数据交换。
- 关闭连接。
-
客户端:
- 初始化 Winsock 库。
- 创建套接字并连接到服务器。
- 发送数据到服务器并接收服务器响应。
- 关闭连接。
服务器端代码
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库
// 服务器端
int main() {
WSADATA wsaData;
SOCKET listenSocket, clientSocket;
sockaddr_in serverAddr, clientAddr;
int clientAddrSize = sizeof(clientAddr);
char recvBuffer[512];
// 初始化 Winsock 库
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Winsock initialization failed." << std::endl;
return 1;
}
// 创建监听套接字
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed." << std::endl;
WSACleanup();
return 1;
}
// 配置服务器地址
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8080); // 设置端口
serverAddr.sin_addr.s_addr = INADDR_ANY; // 监听所有接口
// 绑定套接字到地址
if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Bind failed." << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
// 开始监听客户端连接
if (listen(listenSocket, 1) == SOCKET_ERROR) {
std::cerr << "Listen failed." << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
std::cout << "Waiting for client connection..." << std::endl;
// 接受客户端连接
clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &clientAddrSize);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Accept failed." << std::endl;
closesocket(listenSocket);
WSACleanup();
return 1;
}
std::cout << "Client connected!" << std::endl;
// 接收数据
int bytesReceived = recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (bytesReceived > 0) {
recvBuffer[bytesReceived] = ' '; // 添加字符串结束符
std::cout << "Received from client: " << recvBuffer << std::endl;
// 发送响应
std::string response = "Hello from server!";
send(clientSocket, response.c_str(), response.length(), 0);
} else {
std::cerr << "Receive failed." << std::endl;
}
// 关闭套接字
closesocket(clientSocket);
closesocket(listenSocket);
WSACleanup();
return 0;
}
客户端代码
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库
// 客户端
int main() {
WSADATA wsaData;
SOCKET clientSocket;
sockaddr_in serverAddr;
char sendBuffer[512], recvBuffer[512];
// 初始化 Winsock 库
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "Winsock initialization failed." << std::endl;
return 1;
}
// 创建客户端套接字
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Socket creation failed." << std::endl;
WSACleanup();
return 1;
}
// 设置服务器地址
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8080); // 设置端口
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP 地址
// 连接到服务器
if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
std::cerr << "Connection failed." << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
std::cout << "Connected to server!" << std::endl;
// 发送数据
std::string message = "Hello from client!";
send(clientSocket, message.c_str(), message.length(), 0);
// 接收响应
int bytesReceived = recv(clientSocket, recvBuffer, sizeof(recvBuffer), 0);
if (bytesReceived > 0) {
recvBuffer[bytesReceived] = ' '; // 添加字符串结束符
std::cout << "Received from server: " << recvBuffer << std::endl;
} else {
std::cerr << "Receive failed." << std::endl;
}
// 关闭套接字
closesocket(clientSocket);
WSACleanup();
return 0;
}
代码解释
服务器端代码:
- 初始化 Winsock:通过调用
WSAStartup
来初始化 Winsock 库,准备进行网络操作。 - 创建套接字:调用
socket
创建一个 TCP 套接字(SOCK_STREAM
)。 - 绑定地址:使用
bind
将套接字绑定到指定的端口8080
上,这样客户端才能通过该端口连接。 - 监听连接:通过
listen
函数监听客户端的连接请求,等待客户端连接。 - 接收连接:使用
accept
函数接受客户端连接,一旦连接成功,服务器开始接收数据。 - 接收数据并发送响应:使用
recv
接收客户端发送的数据,然后通过send
向客户端发送响应。 - 清理:关闭套接字,并调用
WSACleanup
清理 Winsock。
客户端代码:
- 初始化 Winsock:通过调用
WSAStartup
初始化 Winsock 库。 - 创建套接字:通过
socket
创建一个 TCP 套接字。 - 连接服务器:通过
connect
将客户端连接到服务器(IP 地址为127.0.0.1
,端口为8080
)。 - 发送数据:使用
send
发送数据到服务器。 - 接收响应:使用
recv
接收服务器的响应数据。 - 清理:关闭套接字,并调用
WSACleanup
清理 Winsock。
测试与运行
-
运行服务器端:
- 先运行服务器端程序,它将开始监听端口
8080
。
- 先运行服务器端程序,它将开始监听端口
-
运行客户端:
- 运行客户端程序,客户端会连接到本地服务器并发送消息。
- 服务器接收到消息后会回复客户端,客户端接收服务器的响应并显示。
示例输出
-
服务器端(假设客户端发送消息
"Hello from client!"
):
Waiting for client connection...
Client connected!
Received from client: Hello from client!
客户端(收到服务器的响应 "Hello from server!"
):
Connected to server!
Received from server: Hello from server!
总结
通过这个项目,我们实现了一个简单的 TCP 网络通信程序,包含服务器端和客户端。通过使用 Winsock 库的基本功能,我们能够在 C++ 中创建一个 TCP 服务器并与客户端进行通信。此代码可以作为更复杂网络应用程序的基础。