这是一个 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)