在本篇博客中,我们将使用 C++ 和 Windows Socket(Winsock)API 实现一个简单的 TCP 客户端与服务器之间的通信程序。该程序支持一对一连接,客户端可以向服务器发送消息,服务器接收并回传相同的消息。
TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。它广泛用于网络通信中,确保数据能够准确无误地传输。
本文实现了一个 点对点 的 TCP 通信系统,包含两个部分:
- 服务端(Server):监听指定端口,等待客户端连接,并接收和回传数据。
- 客户端(Client):连接到服务端,发送数据并接收回传信息。
项目使用的是 Windows 平台下的 Winsock2 API,适用于 Visual Studio 编译环境。
💡 功能说明
- 支持一对一连接(单线程)
- 服务端持续监听,客户端可多次发送数据
- 消息回显功能(Echo Server):服务端将收到的消息原样返回给客户端
- 输入
exit
可退出客户端程序
🧩 代码实现
🖥️ 服务端代码(TCP_Server.cpp)
// TCP_Server.cpp: 定义 TCP 服务端程序的入口点
//
#include <iostream>
#include <WinSock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
// 初始化 Winsock 库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "WSAStartup failed!" << endl;
return -1;
}
// 创建监听 socket
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket == INVALID_SOCKET)
{
cout << "Socket creation failed." << endl;
WSACleanup();
return -1;
}
// 配置本地地址信息
struct sockaddr_in local = { 0 };
local.sin_family = AF_INET; // IPv4 地址族
local.sin_port = htons(8080); // 监听端口号
local.sin_addr.s_addr = inet_addr("127.0.0.1"); // 本地回环地址
// 绑定 socket 到本地地址
if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
{
cout << "Bind failed: " << WSAGetLastError() << endl;
closesocket(listen_socket);
WSACleanup();
return -1;
}
// 开始监听
listen(listen_socket, 10);
cout << "Server is listening on port 8080..." << endl;
while (true)
{
// 接受客户端连接
SOCKET client_socket = accept(listen_socket, NULL, NULL);
if (client_socket == INVALID_SOCKET)
{
cout << "Accept failed: " << WSAGetLastError() << endl;
continue;
}
cout << "Client connected." << endl;
char buffer[1024] = { 0 };
while (true)
{
// 接收客户端数据
int ret = recv(client_socket, buffer, sizeof(buffer), 0);
if (ret <= 0)
{
cout << "Client disconnected." << endl;
break;
}
cout << "Received data: " << buffer << endl;
// 将收到的数据原样返回
send(client_socket, buffer, strlen(buffer), 0);
}
// 关闭客户端 socket
closesocket(client_socket);
}
// 关闭监听 socket
closesocket(listen_socket);
// 清理 Winsock 资源
WSACleanup();
return 0;
}
📱 客户端代码(TCP_Client.cpp)
// TCP_Client.cpp: 定义 TCP 客户端程序的入口点
//
#include <iostream>
#include <WinSock2.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main()
{
// 初始化 Winsock 库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
cout << "WSAStartup failed!" << endl;
return -1;
}
// 创建客户端 socket
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == INVALID_SOCKET)
{
cout << "Socket creation failed." << endl;
WSACleanup();
return -1;
}
// 设置服务器地址
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET; // IPv4 地址族
server_addr.sin_port = htons(8080); // 服务器端口号
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器 IP 地址
// 连接服务器
if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR)
{
cout << "Connect to server failed: " << WSAGetLastError() << endl;
closesocket(client_socket);
WSACleanup();
return -1;
}
cout << "Connected to server at 127.0.0.1:8080" << endl;
char send_buffer[1024] = { 0 };
char recv_buffer[1024] = { 0 };
while (true)
{
// 输入要发送的消息
cout << "Enter message to send (type 'exit' to quit): ";
cin.getline(send_buffer, sizeof(send_buffer));
// 发送消息到服务器
int send_len = send(client_socket, send_buffer, strlen(send_buffer), 0);
if (send_len == SOCKET_ERROR)
{
cout << "Send failed: " << WSAGetLastError() << endl;
break;
}
if (strcmp(send_buffer, "exit") == 0)
{
cout << "Exiting..." << endl;
break;
}
// 接收服务器响应
int recv_len = recv(client_socket, recv_buffer, sizeof(recv_buffer) - 1, 0);
if (recv_len <= 0)
{
cout << "Server disconnected or error occurred." << endl;
break;
}
recv_buffer[recv_len] = '\0'; // 确保字符串结尾
cout << "Server response: " << recv_buffer << endl;
}
// 关闭 socket 并清理 Winsock 资源
closesocket(client_socket);
WSACleanup();
return 0;
}
✅ 运行顺序:
- 先启动服务端程序:
TCP_Server.exe
- 再启动客户端程序:
TCP_Client.exe
- 在客户端输入任意文本,服务端会回传相同内容
- 输入
exit
即可退出客户端