0
点赞
收藏
分享

微信扫一扫

TCP滑动窗口算法

class CPacket{
public:
WORD sHead;//固定位FE FF
DWORD nLength;//包长度(从控制命令开始,到和校验结束)
WORD sCmd;//控制命令
std::string strData;//包数据,不含其他成员
WORD sSum;//和校验
std::string strOut;//整个包的数据
CPacket(const BYTE* pData, size_t& nSize) {//但凡包不完整的情况都把nSize置零
//assert(!(nSize == BUFFER_SIZE));
size_t i = 0;
for (i = 0; i < nSize; i++) {//过滤掉无效的包
if (*(WORD*)(pData + i) == 0xFEFF) {//如果一个包超过缓冲区大小,这东西搞不好会死循环
sHead = *(WORD*)(pData + i);
i += 2;
break;
}
}
if (i + 4 + 2 + 2 > nSize) {//包数据可能不全,或者包头未能全部接收到
nSize = 0;
return;
}
nLength = *(DWORD*)(pData + i); i += 4;
if (nLength + i > nSize) {//包没接收全
nSize = 0;
return;
}
sCmd = *(WORD*)(pData + i); i += 2;
if (nLength > 4) {//协议约定nLength包含2字节nCmd和2字节sSum
strData.resize(nLength - 2 - 2);
memcpy((void*)strData.c_str(), pData + i, nLength - 4);
TRACE("%s\r\n", strData.c_str() + 12);
i += nLength - 4;
}
sSum = *(WORD*)(pData + i); i += 2;//使i指向下一个包
WORD sum = 0;
for (size_t j = 0; j < strData.size(); j++)
{
sum += BYTE(strData[j]) & 0xFF;
}
if (sum == sSum) {//一个包成功解析完成
nSize = i;//head+length+sizeof(length)
return;
}
nSize = 0;
}
};

class CClientSock{
public:
CPacket m_packet;
int DealCommand() {
if (m_sock == -1) return -1;
char* buffer = m_buffer.data();
static size_t index = 0;
while (true) {
if (index == BUFFER_SIZE) AfxMessageBox(_T("指定的缓冲区大小不足"));
size_t len = recv(m_sock, buffer + index, BUFFER_SIZE - index, 0);//这里出现了粘包
if ((len <= 0) && index == 0) {
return -1;
}
//Dump((BYTE*)buffer, index);
index += len;
len = index;
m_packet = CPacket((BYTE*)buffer, OUT len);//获取到一个完整的包后构造函数才会修改len的值使之为一个完整包的字节大小,否则修改为0
if (len > 0) {//if (len == m_packet.nLength+6) {//经过上一步的操作len的值只用两种情况,0或者m_packet.nLength+6
memmove(buffer, buffer + len, BUFFER_SIZE - len);
index -= len;
return m_packet.sCmd;//发生粘包的情况返回后再次进入将导致缓冲区从0开始读取
}
}
return -1;
}
};

举报

相关推荐

0 条评论