QT 处理TCP粘包问题

QT处理TCP粘包问题

处理粘包的方式是在消息头部加上消息总长度。

采用该格式:

消息总长度len(4字节)+命令字commandId(4字节)+消息msg

思路是用一个buffer,每次有消息就读完,然后判断buffer长度,收到四字节长度len后,根据len收消息,当buffer.size()>=len,这时已经收到一个完整的包就可以处理了,处理完后就将buffer前len个字节删除掉,如此反复。

//socket有数据到来就读
connect(m_socket, SIGNAL(readyRead()), this, SLOT(ReadData()));
 
void Foo::ReadData()
{
	m_buf->append(m_socket->readAll());	//buf是QByteArray指针,可以在类内定义
 
	int ret = 1;
	while (ret > 0)
	{
		ret = TryDecode(*m_buf);
		if (ret < 0)
	        qDebug() << "TryDecode() failed";
		else if (ret > 0)
			m_buf->remove(0, ret);
	}
}
 
int Foo::TryDecode(QByteArray& buf)
{
	if (buf.size() < 4)
		return 0;
 
	quint32 len = qFromBigEndian(*(qint32*)buf.data());
	//限制长度
	if (len > 1024 * 1024 * 1024)
		return -1;
 
	if (buf.size() >= len)
	{
		qint32 commandId = qFromBigEndian(*(qint32*)(buf.data() + 4));
		qDebug() << "recv commandId: " << commandId;
		if (commandId == MsgType::heartbeat)
		    qDebug() << "recv heartbeat";
		if (commandId == MsgType::other)
		{
		    //处理other消息		
		}
		return len;
	}
	return 0;
}

常见数据传输场景

一、概念

1)组包。

简单的说就是tcp协议把过大的数据包分成了几个小的包传输,接收方要把同一组的数据包重新组合成一个完整的数据包。

2)半包。

指接受方没有接受到一个完整的包,只接受了部分,这种情况主要是由于TCP为提高传输效率,将一个包分配的足够大,导致接受方并不能一次接受完

3)粘包与分包。

粘包:指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。

分包:指在出现粘包的时候我们的接收方要进行分包处理。

二、发送端解决办法

(1) 可以每次发送同样大小的包,过大的包不予发送,过小的包,后面部分用固定的字符’\0’进行填充。

(2)将流按字符处理,抽出一个字符做转义字符(通常Java用’\’来做转义字符,比如”\n”表示换行)。

(3)在发送方发送一个包的时候,先将这个包的长度发送给对方(一般是4个字节表示包长),然后再将包的内容发送过去.接收方先接收4个字节,看看包的长度,然后按照长度来接收包。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

路过的小熊~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值