C++实现TCP消息传递客户端与服务器
在C++中,使用TCP协议进行消息传递是一种常见的网络编程应用。TCP是一种面向连接的可靠传输协议,能够确保数据包按序无误地到达目标。我们可以使用C++中的 socket
API来实现TCP客户端与服务器的消息传递。
一、TCP通信基本流程
1.1 服务器端流程
- 创建Socket:使用
socket()
系统调用创建一个套接字。 - 绑定Socket:使用
bind()
将套接字绑定到指定的IP地址和端口。 - 监听连接:使用
listen()
监听来自客户端的连接请求。 - 接受连接:使用
accept()
接受客户端的连接。 - 接收与发送消息:使用
recv()
接收客户端的消息,使用send()
发送响应。 - 关闭连接:通信结束后,使用
close()
关闭套接字。
1.2 客户端流程
- 创建Socket:使用
socket()
创建套接字。 - 连接服务器:使用
connect()
连接到服务器的IP地址和端口。 - 发送与接收消息:使用
send()
发送消息,使用recv()
接收服务器的响应。 - 关闭连接:通信结束后,使用
close()
关闭连接。
二、服务器端代码实现
下面是一个简单的TCP服务器的C++实现,服务器将接受来自客户端的连接,并与客户端进行消息传递。
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
const char *response = "Message received";
// 1. 创建套接字
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == 0) {
std::cerr << "Socket creation failed" << std::endl;
return -1;
}
// 2. 配置地址和端口
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // 绑定到本地所有IP地址
address.sin_port = htons(PORT); // 设置端口
// 3. 绑定套接字
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
std::cerr << "Bind failed" << std::endl;
return -1;
}
// 4. 监听连接
if (listen(server_fd, 3) < 0) {
std::cerr << "Listen failed" << std::endl;
return -1;
}
std::cout << "Waiting for connections on port " << PORT << std::endl;
// 5. 接受连接
new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
if (new_socket < 0) {
std::cerr << "Accept failed" << std::endl;
return -1;
}
// 6. 读取客户端发送的消息
int valread = read(new_socket, buffer, BUFFER_SIZE);
std::cout << "Client: " << buffer << std::endl;
// 7. 发送回应消息
send(new_socket, response, strlen(response), 0);
std::cout << "Response sent to client" << std::endl;
// 8. 关闭套接字
close(new_socket);
close(server_fd);
return 0;
}
代码说明:
- socket():创建一个套接字,指定协议族为IPv4(
AF_INET
),协议类型为TCP(SOCK_STREAM
)。 - bind():将套接字与IP地址和端口绑定。
- listen():开始监听传入的连接请求,
3
表示监听队列的最大连接数。 - accept():接受一个客户端连接。
- read():从客户端读取数据。
- send():向客户端发送数据。
- close():关闭套接字,释放资源。
三、客户端代码实现
客户端代码的实现与服务器端类似,只是客户端主动发起连接,并向服务器发送消息。
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
const char *message = "Hello from client";
char buffer[BUFFER_SIZE] = {0};
// 1. 创建套接字
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
std::cerr << "Socket creation failed" << std::endl;
return -1;
}
// 2. 配置服务器地址和端口
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// 将IP地址转换为二进制格式
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
std::cerr << "Invalid address/ Address not supported" << std::endl;
return -1;
}
// 3. 连接服务器
if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
std::cerr << "Connection failed" << std::endl;
return -1;
}
// 4. 发送消息
send(sock, message, strlen(message), 0);
std::cout << "Message sent to server" << std::endl;
// 5. 接收服务器的回应
int valread = read(sock, buffer, BUFFER_SIZE);
std::cout << "Server: " << buffer << std::endl;
// 6. 关闭套接字
close(sock);
return 0;
}
代码说明:
- socket():创建客户端套接字。
- inet_pton():将字符串形式的IP地址转换为二进制形式,供
connect()
使用。 - connect():发起与服务器的连接请求。
- send():向服务器发送数据。
- read():从服务器接收回应。
- close():关闭连接。
四、运行步骤
4.1 编译服务器和客户端代码
分别将上述服务器和客户端代码保存为 server.cpp
和 client.cpp
,然后使用 g++
编译。
g++ server.cpp -o server
g++ client.cpp -o client
4.2 启动服务器
首先启动服务器程序:
./server
服务器会监听 8080
端口,等待客户端连接。
4.3 启动客户端
在另一个终端中,运行客户端程序:
./client
客户端将连接服务器,并发送消息“Hello from client”。
4.4 查看结果
服务器和客户端将会输出相应的消息传递结果:
- 服务器会显示收到的客户端消息,并发送回应“Message received”。
- 客户端将会收到服务器的回应。
五、总结
本示例通过C++实现了一个基本的TCP消息传递系统,包括客户端与服务器的通信流程。服务器负责监听端口,接受客户端连接并进行消息交互,而客户端主动连接服务器并发送消息。
核心操作总结:
- Socket创建:通过
socket()
创建通信套接字。 - 服务器绑定和监听:服务器通过
bind()
绑定IP和端口,并通过listen()
监听连接请求。 - 客户端连接:客户端通过
connect()
连接服务器。 - 消息收发:使用
send()
和recv()
进行消息传递。 - 资源管理:使用
close()
关闭套接字,释放资源。
通过这些步骤,我们可以在C++中实现稳定的TCP消息传递系统,适用于需要可靠数据传输的场景。