Qt解决TCP快速拆包问题

0 背景

一般使用TCP传输数据都会涉及到粘包和拆包的问题,而Qt写的程序多作为客户端,因此主要解决的问题是拆包的问题。面对一次发来了大量的数据包,但是信号却只触发一次,也就是只做了一次拆分了,那就会导致有一部分后面的数据包没有得到处理,那怎么处理这种情况呢?

1 处理

使用递归处理,设置递归条件来再次处理,设置递归边界作为跳出处理。
例如:

	//套接字
	QTcpSocket* tcpSocket;
	
    qint64 totalBytes = 0;//发送数据的总大小
    qint64 receivedBytes = 0;//已收到的
    QByteArray infoBlock;//帧体内容
    QByteArray inBlock;//临时存储的数据

    QByteArray s_frameHead;//帧头
    QByteArray s_frameContent;//帧体
    QByteArray s_frameTail;//帧位

    ///客户端
    //建立套接字连接
    tcpSocket = new QTcpSocket(this);
    //处理接受连接 &QTcpSocket::connected
    connect(tcpSocket, &QAbstractSocket::connected, this, &ShowImage::receiveConnect);

关联信号和槽函数

 //接受数据
    connect(tcpSocket, &QAbstractSocket::readyRead, this, &ShowImage::dealReceiveData);
    //断开连接
    connect(tcpSocket, &QAbstractSocket::disconnected, this, &ShowImage::tcpDisconnected);
    //显示错误
    connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(displayError(QAbstractSocket::SocketError)));

编写处理数据的槽函数:

void dealReceiveData(){
//递归边界:跳出处理
	if(tcpSocket->bytesAvailable() == 0) return;
	
	//处理帧头
        if(receivedBytes < sizeof (qint64) && infoBlock.length() == 0){
             if(tcpSocket->bytesAvailable() >= sizeof (qint64) && s_frameHead.size() == 0){
                   s_frameHead = tcpSocket->read(sizeof (qint64));
//qDebug()<<"s_frameHead:"<<s_frameHead.toHex().toUpper();
               }else{
// qDebug()<<"接收头返回";
                 return;
             }
        }
        //持续接收帧体数据
	if(receivedBytes < totalBytes && tcpSocket->bytesAvailable() > 0){
            //QByteArray inBlock = tcpSocket->readAll();
           if(tcpSocket->bytesAvailable() >= (totalBytes - receivedBytes)){
                inBlock = tcpSocket->read(totalBytes - receivedBytes);
           }else{
                inBlock = tcpSocket->readAll();
           }

            infoBlock.append(inBlock);

            receivedBytes += inBlock.size();
//qDebug()<<"inBlock:"<<byteArrayToHexStr(inBlock);
//qDebug()<<"持续接收receivedBytes:"<<receivedBytes;
            inBlock.resize(0);

        }
        //一帧数据收满开始处理
	 if(receivedBytes == totalBytes){
			//处理
		}
		//如果还是有残留数据,再递归处理数据
		//此处还可以增加特判帧头里的类型字段,来判断是否要递归立即处理,还是等下次数据来触发信号后再处理
	        if(tcpSocket->bytesAvailable() > 0 )){
            dealReceiveData();
        }

}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 岁月 设计师:pinMode 返回首页