自定义包的设计与实现

这是一个 CPacket 类,用于解析包含固定格式的数据。该类的成员变量包括固定包头 sHead、包长度 nLength、控制命令 sCmd、包数据 strData 和和校验 sSum。

构造函数:

CPacket():默认构造函数,初始化成员变量。

CPacket(const BYTE* pData, size_t& nSize):参数化构造函数,用于解析传入的数据(pData),并根据解析结果更新传入的数据大小nSize。如果解析成功,nSize 将被更新为实际有效数据的大小。

解析包数据:

通过循环遍历传入的数据,查找固定包头 0xFEFF 的位置。
如果找到包头,解析包的其他字段,包括包长度 nLength、控制命令 sCmd、包数据 strData 和和校验 sSum。
在解析过程中,对包数据的完整性进行了检查,确保包头和其他字段都能正确解析。
如果包的数据完全接收,并且和校验通过,更新传入的 nSize 为实际解析的包大小。

#pragma pack(push)
#pragma pack(1)
class CPacket
{
public:
	CPacket() :sHead(0),nLength(0),sCmd(0),sSum(0) {}
	// 复制构造函数
	CPacket(const CPacket& pack) {
		sHead = pack.sHead;
		nLength = pack.nLength;
		sCmd = pack.sCmd;
		strData = pack.strData;
		sSum = pack.sSum;
	}
	// 运算符重载
	CPacket& operator=(const CPacket& pack) {
		if (this != &pack) {
			sHead = pack.sHead;
			nLength = pack.nLength;
			sCmd = pack.sCmd;
			strData = pack.strData;
			sSum = pack.sSum;
		}
		return *this;
	}

	// 打包
	CPacket(WORD nCmd, const BYTE* pData, size_t nSize) {
		sHead = 0xFEFF;
		nLength = (DWORD)nSize + sizeof(WORD) * 2;
		sCmd = nCmd;
		if (nSize > 0) {
			strData.resize(nSize);
			memcpy((void*)strData.c_str(), pData, nSize);
		}
		else 
		{
			strData.clear();
		}
		sSum = 0;
		for (size_t j = 0; j < strData.size(); j++)
		{
			sSum += BYTE(strData[j]) & 0xff;
		}
	}

	// 解析包数据
	CPacket(const BYTE* pData, size_t& nSize) {
		size_t i = 0;
		for (; i < nSize; i++) {
			if (*(WORD*)(pData + i) == 0xFEFF) {
				sHead = *(WORD*)(pData + i);
				i += sizeof(WORD);
				break;
			}
		}
		// 包数据可能不全,或者包头未能全部接受到
		if ((i + sizeof(DWORD) + sizeof(WORD) + sizeof(WORD)) > nSize) {
			nSize = 0;
			return;
		}
		nLength = *(DWORD*)(pData + i); 
		i += sizeof(DWORD);
		// 包未完全接受,解析失败
		if (nLength + i > nSize) {
			nSize = 0;
			return;
		}
		sCmd = *(WORD*)(pData + i); 
		i += sizeof(WORD);
		if (nLength > sizeof(WORD) * 2) {
			strData.resize(nLength - sizeof(WORD) * 2);
			memcpy((void*)strData.c_str(), pData + i, nLength - sizeof(WORD) * 2);
			i += nLength - sizeof(WORD) * 2;
		}
		sSum = *(WORD*)(pData + i);
		i += 2;
		WORD sum = 0;
		for (size_t j = 0; j < strData.size(); j++) 
		{
			sum += BYTE(strData[j]) & 0xff;
		}
		if (sum == sSum) {
			nSize = i;
			return;
		}
		nSize = 0;//解析失败
	}
	int Size() {//包数据大小
		return nLength + sizeof(WORD) + sizeof(DWORD);
	}
	const char* Data() {//获取包数据
		strOut.resize(Size());
		BYTE* pData = (BYTE*)strOut.c_str();
		*(WORD*)pData = sHead;
		pData += 2;
		*(DWORD*)pData = nLength;
		pData += 4;
		*(WORD*)pData = sCmd;
		pData += 2;
		memcpy(pData, strData.c_str(), strData.size());
		pData += strData.size();
		*(WORD*)pData = sSum;
		return strOut.c_str();
	}
	~CPacket() {}
public:
	WORD sHead;//固定包头 0xFEFF
	DWORD nLength;//包长度(控制命令到和校验)
	WORD sCmd;//控制命令
	std::string strData;//包数据
	WORD sSum;//和校验
	std::string strOut;//整个包的数据
};
#pragma pack(pop)
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值