包的设计
在本项目中,会有文件操作,信息传输,故想着设计一个包来进行解决,并且进行了封装以及构造函数重载来方便操作
详情见代码
//包设计类
class CPacket
{
public:
//构造函数,初始化
CPacket():sHead(0),nLength(0),sCmd(0),sSum(0){}
//数据包封包构造函数,用于把数据封装成数据包
//参数一:命令 参数二:数据指针 参数三:数据大小
CPacket(WORD nCmd, const BYTE* pData, size_t nSize) {
sHead = 0xFEFF;
nLength = nSize + 4;
sCmd = nCmd;
strData.resize(nSize);
memcpy((void*)strData.c_str(), pData, nSize);//数据拷贝
sSum = 0;
for (size_t j = 0; j < strData.size(); j++) {
sSum += BYTE(strData[j]) & 0xFF;
}
}
CPacket(const CPacket& pack) {
sHead = pack.sHead;
nLength = pack.nLength;
sCmd = pack.sCmd;
strData = pack.strData;
sSum = pack.sSum;
}
//数据包解析,将包中的数据分配到成员变量中
//参数一:数据指针 参数二:数据大小
CPacket(const BYTE* pData, size_t& nSize) {//用于包数据解析
size_t i = 0;
for (; i < nSize; i++) {
if (*(WORD*)(pData + i) == 0xFEFF) {//找到包头
i += 2;
sHead = *(WORD*)(pData + i);//提取包头
break;
}
}
//解析未成功
if (i+8>= nSize) {//包数据可能不全,或者包头未能全部接收
nSize = 0;
return;
}
nLength = *(WORD*)(pData + i); i += 4;//读取长度
if (nLength + i > nSize) {//包未完全接收到
nSize = 0;
return;
}
sCmd = *(WORD*)(pData + i); i += 2;//读取命令行
if (nLength > 4) { //数据的长度大于四
strData.resize(nLength - 2 - 2);//设置string的大小
memcpy((void*)strData.c_str(), pData + i, nLength - 4);//读取数据
i += nLength - 4;
}
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;
}
~CPacket(){}
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;
}
int Size() {//获取包数据的大小
return nLength + 6;
}
const char* Data() {//用于解析包,将包数据送入缓冲区
strOut.resize(nLength + 6);
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();//返回整个包
}
public:
WORD sHead;//包头 固定位 此处用0xFE FF 2字节
DWORD nLength;//包长度(从控制命令开始到和校验结束) 4字节
WORD sCmd;//包控制命令 2字节
std::string strData;//包数据
WORD sSum;//和校验
std::string strOut;//整个包的数据
};