1.定义一个TCP接收端粘包处理的函数TcpReadPkg(),将每次TCP套接字接收的数据传入;
2.函数第三个参数all_buffer在外部定义后传入,需要保证只被创建一次;
3.开始先自定义的数据结构ByteArray
4.函数内部,FRAMEHEADER是约定好的头;
注意:大家参考我这里的函数处理的时候按照自己的报文格式处理,此处我需要处理的每帧数据格式如下:
|-- 2byte head --|-- 2byte 其他 --|-- 2byte length(描述data大小)--|-- data --|-- 4byte 其他 --|
自定义的一个数据结构ByteArray,方便处理接收到的内容:
//字节数组 class ByteArray { public: ByteArray(int max_len = ) { this->max_len = max_len; buffer = new char[max_len]; size = 0; } ~ByteArray() { delete buffer; } //大小 int Size() { return size; } //数据 char* Data() { return buffer; } //添加 void append(char* input_buffer, int len) { if (size + len > max_len) return; memcpy(buffer + size, input_buffer, len); size += len; } //删除前面一截 void front_pop(int front_pop_len) { if (size < front_pop_len) return; char* temp = new char[max_len]; memcpy(temp, buffer + front_pop_len, size - front_pop_len); delete buffer; buffer = temp; size -= front_pop_len; } //清空 void clear() { size = 0; } //查找 int find(char* find_buffer, int len) { if (len > size || len < 1) return -1; int index = -1; for (int i = 0; i < size - len + 1; i++) { for (int j = 0; j < len; j++) { if (buffer[i + j] != find_buffer[j]) break; if (j == len - 1) return i; } } return index; } private: int max_len; char* buffer; int size; }
讯享网
TCP接收端粘包处理的函数TcpReadPkg()的实现
讯享网 int TcpReadPkg(char* read_buffer, int read_len, ByteArray &all_buffer)//tcp防粘包解包 { all_buffer.append(read_buffer, read_len);//追加数据进自定义缓冲区AllBuffer Ushort head = FRAMEHEADER; int headIndex = all_buffer.find((char*)&head, 2);//报文头位置,找不到返回-1 if(-1 == headIndex && all_buffer.Size() >= 6)//整个AllBuffer无报文头,清空AllBuffer防止无效信息累积 all_buffer.clear(); Ushort length = 0;//包头报文长度信息 while(-1 != headIndex)//数据中有报文头就循环 { all_buffer.front_pop(headIndex);//去掉报头前的 if(all_buffer.Size() < 6)//报头后长度信息不完整,下次接收数据再处理 break; memcpy(&length, all_buffer.Data() + 4, 2);//读取长度信息,2字节length if(length > 50000)//根据需求,这里不会大于50000 { std::cout << "[Error] length > 50000, length = " << length << std::endl; all_buffer.front_pop(6);//去掉整个报头前的 length = 0; } if(all_buffer.Size() >= length + 6 + 4 && length > 0)//长度足够 { std::cout << "all_buffer.size = " << all_buffer.Size() << ", length = " << length << std::endl; //有效data在这里 int actual_length = length + 6 + 4; //all_buffer.Data()就是解出来的一包数据首地址,包括头尾 //在这里处理解包的数据 all_buffer.front_pop(length + 6 + 4);//去掉已获取的部分 } else//长度不够,下次接收数据再处理 break; headIndex = all_buffer.find((char*)&head, 2);//刷新报文头位置,找不到返回-1 } return 0; }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/117938.html