当前位置:网站首页>Qt TCP 分包粘包的解决方法
Qt TCP 分包粘包的解决方法
2022-07-06 05:16:00 【hitzsf】
1. 为什么TCP会有粘包分包半包现象 ?
TCP产生粘包分包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。
发送方引起的原因是由TCP协议本身造成的
TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。这么做优点也很明显,就是为了减少广域网的小分组数目,从而减小网络拥塞的出现。总的来说就是:发送端发送了几次数据,接收端一次性读取了所有数据,造成多次发送一次读取;通常是网络流量优化,把多个小的数据段集满达到一定的数据量,从而减少网络链路中的传输次数。
接收方引起的原因是由于接收方用户进程不及时接收数据,从而导致粘包现象。
因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。
分包或半包是指在出现粘包的时候我们的接收方要进行分包处理。
分包现象在长连接中都会出现。总的来说就是:发送端发送了数量比较多的数据,接收端读取数据时候数据分批到达,造成一次发送多次读取(在实践中,客户端开启TCP_NODELAY后,服务端仍沾包,所以这里是多次发送一次读取);通常和网络路由的缓存大小有关系,一个数据段大小超过缓存大小,那么就要拆包发送。
2. 怎么处理粘包分包现象?
tcp粘包、半包的处理方式:
一是采用分隔符的方式,采用特殊的分隔符作为一个数据包的结尾,例如:”$$”;
二是采用给每个包的特定位置(如包头两个字节)加上数据包的长度信息,另一端收到数据后根据数据包的长度截取特定长度的数据解析。
3. Qt 处理粘包半包的demo
为了简单显示,使用 QList< QByteArray > 来模拟 socket 接受到多次数据的情况,并且一个完整的数据包以“$$”结束,例如:1111$$
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
// 模拟粘包半包的数据
QList<QByteArray> recvMsgs = {
"1111$$2222$$xxxxx","3333$$444$$yyyy"};
static QByteArray halfData="0000"; // 上一次遗留的半包数据
for (int var = 0; var < recvMsgs.size (); ++var) {
auto recvMsg = recvMsgs.at (var);
// 打包数据
int idx = 0;
while (idx != -1) {
// 从idx位置开始查找$$的位置
int postion = recvMsg.indexOf ("$$",idx); // 解决粘包问题 "1111$$2222$$xxxxx"
if(postion != -1) {
// 获取$$前的数据,不包括$$
auto byte = recvMsg.mid(idx, postion - idx);
if(!halfData.isEmpty ()){
byte = halfData+byte;
halfData.clear ();
}
qDebug() << byte;
postion += 2;
}
else{
// 如果有半包现象,则把最后一个"$$"后的数据保存起来,暂时不使用
if(idx < recvMsg.length ()){
halfData = recvMsg.mid (idx);
}
}
idx = postion;
}
qDebug() << "剩下的半包数据:" << halfData;
}
}
运行结果:
"00001111"
"2222"
剩下的半包数据: "xxxxx"
"xxxxx3333"
"444"
剩下的半包数据: "yyyy"
参考应用:
边栏推荐
- 图论的扩展
- [NOIP2009 普及组] 分数线划定
- [classic example] binary tree recursive structure classic topic collection @ binary tree
- Cve-2019-11043 (PHP Remote Code Execution Vulnerability)
- Easy to understand I2C protocol
- [noip2008 improvement group] stupid monkey
- Nacos TC setup of highly available Seata (02)
- [leetcode daily question] number of enclaves
- On the solution of es8316's audio burst
- Modbus协议通信异常
猜你喜欢
Unity Vector3. Use and calculation principle of reflect
yolov5 tensorrt加速
Configuration file converted from Excel to Lua
Golang -- TCP implements concurrency (server and client)
Postman pre script - global variables and environment variables
The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
Ad20 is set with through-hole direct connection copper sheet, and the bonding pad is cross connected
Postman assertion
【LeetCode】18、四数之和
注释、接续、转义等符号
随机推荐
图数据库ONgDB Release v-1.0.3
GAMES202-WebGL中shader的編譯和連接(了解向)
[leetcode] 18. Sum of four numbers
用StopWatch 统计代码耗时
【LGR-109】洛谷 5 月月赛 II & Windy Round 6
F12 solve the problem that web pages cannot be copied
2022 half year summary
Lepton 无损压缩原理及性能分析
Nestjs配置文件上传, 配置中间件以及管道的使用
Application of Flody
注释、接续、转义等符号
Raspberry pie 3.5-inch white screen display connection
Rce code and Command Execution Vulnerability
Figure database ongdb release v-1.0.3
Postman测试报告
February 12 relativelayout
ISP learning (2)
Upload nestjs configuration files, configure the use of middleware and pipelines
pix2pix:使用条件对抗网络的图像到图像转换
Steady, 35K, byte business data analysis post