当前位置: 首页 > article >正文

C++11实现TCP网络通讯服务端处理逻辑简化版

以下是使用C++11实现的TCP服务端处理逻辑,包含循环读取数据、帧头检测(AABBCC)及4376字节数据包处理:

cpp

#include <iostream>
#include <vector>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
constexpr size_t PACKET_SIZE = 4376; // 完整数据包大小(含3字节帧头)
constexpr size_t HEADER_SIZE = 3; // 帧头大小
constexpr uint8_t FRAME_HEADER[] = {0xAA, 0xBB, 0xCC}; // 帧头标识
// 查找缓冲区中的帧头位置
auto find_frame_header(const std::vector<char>& buffer) {
for (size_t i = 0; i <= buffer.size() - HEADER_SIZE; ++i) {
bool match = true;
for (size_t j = 0; j < HEADER_SIZE; ++j) {
if (static_cast<uint8_t>(buffer[i+j]) != FRAME_HEADER[j]) {
match = false;
break;
}
}
if (match) return buffer.begin() + i;
}
return buffer.end();
}
// 数据包处理函数(示例)
void process_packet(const char* data) {
// 这里添加实际业务逻辑
std::cout << "Received valid packet!" << std::endl;
}
int main() {
// 1. 创建TCP socket
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
std::cerr << "Socket creation failed!" << std::endl;
return 1;
}
// 2. 绑定地址
sockaddr_in server_addr{};
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(8080); // 监听端口
if (bind(server_fd, (sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
std::cerr << "Bind failed!" << std::endl;
close(server_fd);
return 1;
}
// 3. 开始监听
if (listen(server_fd, 5) == -1) {
std::cerr << "Listen failed!" << std::endl;
close(server_fd);
return 1;
}
// 4. 接受客户端连接
sockaddr_in client_addr{};
socklen_t addr_len = sizeof(client_addr);
int client_fd = accept(server_fd, (sockaddr*)&client_addr, &addr_len);
if (client_fd == -1) {
std::cerr << "Accept failed!" << std::endl;
close(server_fd);
return 1;
}
std::vector<char> buffer;
buffer.reserve(PACKET_SIZE * 2); // 预留双倍数据包空间
while (true) {
// 5. 循环接收数据
char temp_buf[1024];
ssize_t bytes_received = recv(client_fd, temp_buf, sizeof(temp_buf), 0);
if (bytes_received <= 0) {
std::cout << "Connection closed by client" << std::endl;
break;
}
// 将接收数据追加到缓冲区
buffer.insert(buffer.end(), temp_buf, temp_buf + bytes_received);
// 6. 处理缓冲区数据
while (true) {
auto header_pos = find_frame_header(buffer);
if (header_pos == buffer.end()) {
// 未找到帧头,保留最后两个字节防止丢弃可能的帧头前缀
if (buffer.size() >= HEADER_SIZE - 1) {
buffer.erase(buffer.begin(), buffer.end() - (HEADER_SIZE - 1));
} else {
buffer.clear();
}
break;
}
// 检查剩余数据是否足够
if (buffer.end() - header_pos >= PACKET_SIZE) {
// 7. 处理完整数据包
process_packet(&*header_pos);
// 8. 移除已处理数据(包含帧头)
buffer.erase(buffer.begin(), header_pos + PACKET_SIZE);
} else {
// 数据不足,等待下次接收
break;
}
}
}
// 清理资源
close(client_fd);
close(server_fd);
return 0;
}

关键实现细节说明:

  1. 缓冲区管理
    • 使用std::vector<char>作为动态缓冲区,自动管理内存
    • 预分配双倍数据包大小空间(PACKET_SIZE * 2)减少内存重分配
  2. 帧头检测
    • find_frame_header函数逐字节比对帧头模式
    • 使用uint8_t类型转换避免符号扩展问题
    • 精确匹配连续3字节的帧头序列
  3. 粘包处理
    • 当未找到完整帧头时,保留最后2字节(HEADER_SIZE - 1)防止丢弃可能的帧头前缀
    • 找到帧头后检查剩余数据是否满足完整数据包长度
  4. 数据包处理
    • 检测到完整数据包后调用process_packet处理
    • 每次处理后从缓冲区移除已处理数据(包含帧头)
  5. 异常处理
    • 检测客户端断开连接(recv返回0)
    • 基础错误检查(socket创建、绑定、监听等)

使用注意事项:

  1. 编译时需要链接网络库(Linux下添加-lpthread参数)
  2. 实际使用时需完善以下部分:
    • process_packet函数中的业务逻辑
    • 添加校验和验证(如协议需要)
    • 多客户端支持(可通过多线程/select/epoll实现)
    • 错误日志记录
    • 性能优化(环形缓冲区、零拷贝等)

该实现能够有效处理TCP粘包问题,确保完整数据包的接收和处理,适用于需要固定长度数据包传输的场景。

http://www.lryc.cn/news/2402273.html

相关文章:

  • python3.9带 C++绑定的基础镜像
  • Elasticsearch中的语义搜索(Semantic Search)介绍
  • LabVIEW的AMC架构解析
  • MySQL 索引:为使用 B+树作为索引数据结构,而非 B树、哈希表或二叉树?
  • ubuntu屏幕复制
  • Flutter嵌入式开发实战 ——从树莓派到智能家居控制面板,打造工业级交互终端
  • Spring WebFlux 整合AI大模型实现流式输出
  • 验证电机理论与性能:电机试验平板提升测试效率
  • Vue.js应用结合Redis数据库:实践与优化
  • Simplicity studio SDK下载和安装,创建工程
  • OpenCV——Mac系统搭建OpenCV的Java环境
  • 更新Java的环境变量后VScode/cursor里面还是之前的环境变量
  • 【设计模式-3.4】结构型——代理模式
  • 电脑频繁黑屏怎么办
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Sound Board(音响控制面板)
  • 关于大数据的基础知识(一)——定义特征结构要素
  • chrome使用手机调试触屏web
  • 浅谈量子计算:从实验室突破到产业落地的中国实践
  • 68道Hbase高频题整理(附答案背诵版)
  • python版若依框架开发:项目结构解析
  • 国产linux系统(银河麒麟,统信uos)使用 PageOffice在线编辑word文件保存数据同时保存文件
  • day34- 系统编程之 网络编程(TCP)
  • 鸿蒙jsonToArkTS_工具exe版本来了
  • DeviceNet转Modbus TCP网关的远程遥控接收端连接研究
  • ASP.NET Core 中间件深度解析:构建灵活高效的请求处理管道
  • 开关机、重启、改密、登录:图解腾讯云CVM日常管理核心操作,轻松掌控你的云主机
  • 从0到1认识ElasticStack
  • I2C 外设知识体系:从基础到 STM32 硬件实现
  • vue和uniapp聊天页面右侧滚动条自动到底部
  • 文件索引:数组、二叉树、二叉排序树、平衡树、红黑树、B树、B+树