C++TCP解包(起始符+固定长度)

TCP通信中的丢包粘包问题一直是一个麻烦,特别是通信数据量大而且频繁的场景。不同的通信协议解决方案也有所不同,本文的通信协议为报文设置起始符+结束符。

示例程序设置起始符为"$@#", 固定长度为10。核心思路就是先用一个变量把每次收到的报文都拼起来,根据起始符和固定长度截取包,截取包后剩下的报文用来继续拼接后面的报文。由于缓冲区大小的原因可能会出现报文中间截断,但是TCP是可靠性传输,所以不会出现顺序错乱的问题。关键代码如下:

void WidTcpServer::SlotReadReady()
{
	//解包
	auto funUnPakege = [this](const QByteArray& byteReceive)
	{
		QByteArray strBegin = "$@#"; //起始符  $@#0123456789
		int nPackageSize = 10;  //包的长度
		std::lock_guard<std::mutex> lockTcp(m_mutexTcp); //加锁
		m_strReceive += byteReceive;
		while (m_strReceive.size() >= nPackageSize) //剩余长度大于或者等于一个包的长度就继续查找
		{
			int nBegin = m_strReceive.indexOf(strBegin); //找到第一个起始符
			if (nBegin < 0)
				break;
			int nEndSize = m_strReceive.size() - nBegin - strBegin.size(); //起始符后面的长度
			if (nEndSize >= nPackageSize)
			{
				QByteArray bytePakage = m_strReceive.mid(nBegin + strBegin.size(), nPackageSize); //解析到一个完整的包
				ShowPakage(bytePakage);
				m_strReceive = m_strReceive.right(m_strReceive.size() - nPackageSize - nBegin - strBegin.size()); //截取当前包后面的字符串,用作下一次拼接包
			}
		}
		emit SigShowMessage(QString("Current data:%1").arg(m_strReceive.data()), Qt::blue);
	};
	QByteArray byteReceive = m_pTcpSocket->readAll();
	std::thread threadTcpData(funUnPakege, byteReceive);
	threadTcpData.detach();
}

程序测试:紫色为接收到的包内容,蓝色为当前截取包后剩余的报文内容。

1、两个包一起发,收到两个包

图片

2、发一个半,再发后面半个,也收到两个包

图片

图片

3、中间夹杂其他无效的报文,结果收到两个包并且过滤掉无效报文内容

图片

本工程源码百度网盘 请输入提取码,提取码5032

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++工业软件-Kevin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值