C++实现TCP客户端及服务器Recv数据筛选处理详解

 更新时间:2022年10月09日 16:15:26   作者:中国好公民st  
这篇文章主要为大家介绍了C++实现TCP客户端及服务器Recv数据筛选处理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

对于一个简单的tcp通讯这里我就不再讲述了,今天主要为大家讲解下,如何从::recv中筛选出一个完整包逻辑。

就简单的以客户端为例(服务器接收方也是同样的逻辑),假设服务器一直在频繁发送数据,在recv函数中并不能保证每次接收的都是一个完整的包,当设置recv的缓冲区过大时,就会出现多个包同时接收的问题。

对于这种情况,初出茅庐的我们有时会想不到居然还有多个包共同出现的问题,甚至有些还没学会如何高效的分离出一个有效的数据包。

一般在进行tcp通讯协议时,为了各个指令的区分,通常都会用以下方式进行发送,如下图:

具体的通信协议规格可以按照各个业务需求来定义,这里只是列举了一个简单的例子。

在这篇文章中根据上图中的协议格式,进行举例讲解。

协议标识测试具体
系统标识0x5A
源设备标识0xFCFB
预留字节假设占10个字节
源设备编码根据连接的服务端设备编码,假设这是是0x01(编号1)
命令字具体的业务指令,两个字节
数据长度需要发送的数据长度
数据内容具体业务具体内容
校验码0xEF

在进行tcp通讯时,我们每条指令都是按照这种方式进行发送的,接下来,到了文章的重点部分了,该如何对接收的数据筛选?

根据流程图可以发现,当数据不匹配时,需要重新进行筛选,程序采用了递归的方式进行数据剔除。这里只是展示了内部的流程处理,外部调用该如何呢?

int nTotalSize = 0;
while(this->JudgeValidData(vetRecvData, nTotalSize) == ture)
{
    //接收到了完整包,对包进行处理
}

代码解析

nTotalSize:代表了一个完整数据包的总长度。

vetRecvData:recv函数接收的所有缓冲区内容。

其实上面流程图的内容就是JudgeValidData()的函数处理逻辑。

对于该函数的详细解析:

1:当Tcp缓冲区的数据小于3个字节时,不进行判断

此时字节数据过小,无法判断是不是当前程序中需要的

2:判断包头是不是一致?

上述表格中,举例说明了包头的定义,分别是:0x5A、0xFC、0xFB

那么,我们在判断数据时首先要判断包头是否正确?包头不正确后续也就不需要判断了!

char ch0 = vetRecvData[0]; //系统标识
char ch1 = vetRecvData[1]; //标识1
char ch2 = vetRecvData[2]; //标识2
if((ch0 == 0x5A) && (ch1 == 0xFC) && (ch2 == 0xFB))
{
    //包头正确,进行后续处理
}
else
{
    //包头不正确,剔除数据,默认剔除缓冲区的第一个字节数据
    std::vector<char>::iterator itbegin = vetRecvData.begin();
    vetRecvData.erase(itbegin);
    //重新调用当前函数,递归判断
    return JudgeValidData(vetRecvData, nTotalSize);
}

3:包头匹配后,判断是否达到了数据包的固定协议长度?

在这里说的固定协议长度,就是数据内容之前的字节,在这篇文章中,数据内容之前有19个字节,所以,当vetRecvData的数据总长度 < 19个字节时,不需要处理。

当达到固定协议长度后,说明该缓冲区中存在了有效数据,那么就需要判断实际的数据内容是否达到了整包的标准?

4:判断有效数据是否接收完整?

首先,需要获取当前包需要接收的数据长度。在这里是占用三个字节,分别是:16、17、18这三位

int ndatalen = (unsigned char)pThreadParam->vetRecvData[16] * 256 *256+ (unsigned char)pThreadParam->vetRecvData[17]*256 + (unsigned char)pThreadParam->vetRecvData[18];
nTotalSize = 19 + ndatalen + 1;

如果当前vetRecvData缓冲区的数据 < nTotalSize,说明数据不完整,不判断;反之,缓冲区中存在完整的数据。

5:数据校验位判断

最后,判断下缓冲区完整包的最后一位是否是校验位?

这样,才算是一个完整的一条数据包!

到这里,就算判断完成了,由此可以从一个大的缓冲区中抽取出有用的一组数据。

内部的判断逻辑讲解完之后,接下来就是外部数据使用了。继续上面的这段代码继续讲解~

int nTotalSize = 0;
while(this->JudgeValidData(vetRecvData, nTotalSize) == ture)
{
    //接收到了完整包,对包进行处理
}

接收到一个完整包之后,数据处理过程

1:根据nTotalSize大小从缓冲区中获取有效内容

2:截取出剩余的缓冲区内容,重新赋值

3:对一个完整包数据进行业务处理

将流程转换成代码,如下:

int nTotalSize = 0;
while (this->JudgeValidData(vetRecvData, nTotalSize) == true)
{
	//这一条数据被处理之后,使用一个临时容器存储 处理的 通讯数据
	std::vector<char> vetValidData;
	char* chUseData = new char[nTotalSize];
	memset(chUseData, 0, nTotalSize);
	for (int i = 0; i < vetRecvData.size(); i++)
	{
		if (i < nTotalSize)
		{
			chUseData[i] = vetRecvData[i];
		}
		else
			vetValidData.push_back(vetRecvData[i]);
	}
	//删除 存储所有接收字节的容器 中的数据
	vetRecvData.clear();
	vetRecvData = vetValidData; //重新更新数据信息
	//接收的是整包数据时,进行实际的数据处理
	ProcessingPancelValidData(chUseData, nTotalSize);
	delete[] chUseData;
	chUseData = nullptr;
}

以上就是C++实现TCP客户端及服务器Recv数据筛选处理详解的详细内容,更多关于C++ 客户端 服务器数据筛选的资料请关注脚本之家其它相关文章!

相关文章

  • 深入解析C++中的函数模板和函数的默认参数

    深入解析C++中的函数模板和函数的默认参数

    这篇文章主要介绍了深入解析C++中的函数模板和函数的默认参数,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C语言代码实现2048游戏

    C语言代码实现2048游戏

    这篇文章主要为大家详细介绍了C语言代码实现2048游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • QT5实现UDP通信的示例代码

    QT5实现UDP通信的示例代码

    本文主要介绍了QT5实现UDP通信的示例代码,主要使用QUdpSocket类用于实现UDP通信,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 基于堆的基本操作的介绍

    基于堆的基本操作的介绍

    本篇文章对堆的基本操作进行了详细的分析介绍。需要的朋友参考下
    2013-05-05
  • C语言科学计算入门之矩阵乘法的相关计算

    C语言科学计算入门之矩阵乘法的相关计算

    这篇文章主要介绍了C语言科学计算入门之矩阵乘法的相关计算,文章中还介绍了矩阵相关的斯特拉森算法的实现,需要的朋友可以参考下
    2015-12-12
  • c++实现MD5算法实现代码

    c++实现MD5算法实现代码

    用c++实现了md5算法。包含 md5.h 和md5.cpp 两个文件。主要参考百度百科 “MD5” 原理,代码中变量命名也是参考其中的公式,程序的使用说明在md5.h 文件的末尾注释中
    2013-11-11
  • C++ Boost Parameter超详细讲解

    C++ Boost Parameter超详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C++ boost thread库用法详细讲解

    C++ boost thread库用法详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C++ smart pointer全面深入讲解

    C++ smart pointer全面深入讲解

    一般在C/C++中,如果我们使用了pointer来指向某块heap区域,当不再需要这块区域的时候,我们需要手动删除它。如果忘了的话,就会产生memory leak
    2022-08-08
  • C++实现聊天小程序

    C++实现聊天小程序

    这篇文章主要为大家详细介绍了C++实现聊天小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06

最新评论