16,472
社区成员
发帖
与我相关
我的任务
分享
// 网络包头
struct SNPKHeader
{
SNPKHeader(WORD mainMsg=0, WORD subMsg=0) : m_MainMsg(mainMsg), m_SubMsg(subMsg), m_Size(0) {}
WORD m_MainMsg; // 主消息
WORD m_SubMsg; // 子消息
int m_Size; // 包数据大小(不包含SNPKHeader本身的大小)
};
// 恢复对齐状态
#pragma pack(pop)
我发现我们一直讨论的关键字有误区了.........
“包”这个词是我们定义为通讯协议,里面包含有每个包所代表的含义
但其实我们要讨论的是如何确保网络发送的数据完整性,虽然tcp保证了数据的完整性,但它并不保证数据的结构性
它有可能会把一次发送的数据分成几次接收,也有可能把几次发送的数据合并成一次接收
那么我们要做的只是把每次发送的数据区分开来,而并不是说要把每个数据包区分开(数据包的处理当然是留给下级调用者了)
那么在每次数据发送前定义一个当前发送数据的大小我觉得很有必要
这样就可以告诉接收方我这次发送的数据大小是多少,无论你接收到多少数据,都要按照这个大小来区分每次的数据传输量
我#26楼所说类里面包含了包分析在内,其实是说在类里面处理接受的内容,把内容分成对方每次发送过来的数据大小
// 网络包头
struct SNPKHeader
{
SNPKHeader(WORD mainMsg=0, WORD subMsg=0) : m_MainMsg(mainMsg), m_SubMsg(subMsg), m_Size(0) {}
WORD m_MainMsg; // 主消息
WORD m_SubMsg; // 子消息
int m_Size; // 包数据大小(不包含SNPKHeader本身的大小)
};
// 恢复对齐状态
#pragma pack(pop)
这个我包头是应用层定义的,IOCP封装类不会附加其它字节数据
当我投递recv收到结果后,我会先recv这个包头,然后再recv其中m_Size个字节数据
void AuthSocket::OnRead()
{
uint8 _cmd;
while (1)
{
if (!recv_soft((char*)&_cmd, 1))
return;
size_t i;
///- Circle through known commands and call the correct command handler
for (i = 0; i < AUTH_TOTAL_COMMANDS; ++i)
{
if ((uint8)table[i].cmd == _cmd &&
(table[i].status == STATUS_CONNECTED ||
(_authed && table[i].status == STATUS_AUTHED)))
{
DEBUG_LOG("[Auth] got data for cmd %u recv length %u",
(uint32)_cmd, (uint32)recv_len());
if (!(*this.*table[i].handler)())
{
DEBUG_LOG("Command handler failed for cmd %u recv length %u",
(uint32)_cmd, (uint32)recv_len());
return;
}
break;
}
}
///- Report unknown commands in the debug log
if (i == AUTH_TOTAL_COMMANDS)
{
DEBUG_LOG("[Auth] got unknown packet %u", (uint32)_cmd);
return;
}
}
}