游戏服务器之消息校验
来源:互联网 发布:火石软件三界奇缘 编辑:程序博客网 时间:2024/05/18 02:19
游戏服务器之消息校验是为了防止外挂添加的检查。
设计上:
消息校验分为
1、长度校验
消息需要过滤长度过长的消息
2、消息标识检查
消息需要过滤不符合标识的
3、校验码校验
消息需要过滤校验码不正确的
4、消息编号校验
检查编号正确的才可以转发到场景服务器,否则就踢出该玩家。编号是从0开始,到65535就重新从0开始
消息头的信息
struct base_msg{uint16 reserve;//保留字节(第15位是可用来标识是否压缩(0x4000))uint16 len;//长度(从消息头标识开始计算)uint16 base_flag;//消息头标识(某个固定的值)uint16 base_sum;//交验码uint16 base_index;//消息编号uint8 first;//一级系统指令uint8 second;//二级系统指令...};
1、消息头过滤
分析检验正确的才派送,然后发送到场景进程
1、长度校验大于1.5K,小于消息头长度的包都直接忽略 (ptNull 是消息指针, msglen 消息长度)if (!ptNull || msglen< (MSG_HEAD_SIZE) || msglen >= 1536){error_log("外挂发来(帐号%s,角色(%u,%s),ip:%s):,网关消息解析消息长度出错:%u,发来的消息是(%u,%u)",account,pplayer->id,pplayer->name,getIP(),msglen,ptNull->first,ptNull->second);TerminateWait();return false;}
2、消息标识检查
网关消息标签不正确的需要忽略掉if(MSG_HEAD_FLAG!= ptNull->base_flag){error_log("外挂发来,帐号%s,角色(%u,%s),ip:%s):网关消息标签不正确,消息标签(%u %u),发来的消息是(%u,%u)",account,pplayer->id,pplayer->name,getIP(),MSG_HEAD_FLAG,ptNull->base_flag,ptNull->first,ptNull->second);TerminateWait();return false;}
3、校验码校验
消息校验码校验
if (!calcPacketVerify(ptNull,msglen)){error_log("外挂发来(帐号%s,角色(%u,%s),ip:%s):校验出错,发来的消息是(%u,%u)",account,pplayer->id,pplayer->name,getIP(),ptNull->first,ptNull->second);TerminateWait();return false;}
4、消息编号校验
消息编号检查
if(!checkMsgIndex(ptNull->base_index)){error_log("外挂发来(帐号%s,角色(%u,%s),ip:%s):网关连接的消息报序列不正确,需要的是%u,发来的是%u,消息是(%u,%u)",account,pplayer->id,pplayer->name,getIP(),msg_index,ptNull->base_index,ptNull->first,ptNull->second);TerminateWait();return false;}
2、校验码检查
校验码是从消息体开始的(这里是从一级指令开始的,不包含消息头的消息编号之前的信息),对每个字节异或,并异或两个特殊的key(一个是写死的,一个是分配连接时随机的)。
只有前端发来的校验码是跟后端计算一样的,才算是校验码正确的。
bool gateway_session::calcPacketVerify(const MSG::base_msg *ptNull, const uint32 msglen){const uint8* pBuffer = (const uint8*)ptNull+MSG_HEAD_SIZE;//消息校验从一级指令开始uint16 dwMsgBodySize = msglen-MSG_HEAD_SIZE;//一级指令开始是消息体uint16 ret = 0xAB;//特殊的keyconst uint8 *pb = (const uint8*)pBuffer;while (dwMsgBodySize > 0){ret ^= *pb;dwMsgBodySize--;pb++;}//计算校验码ret ^= (uint16)(loginTempID & 0xFFFF);//登录时分配的临时id作为校验的keyif(ret != ptNull->base_sum){error_log("校验出错,帐号%s,校验码(正确的是%u,发来的是%u)",account,ret,ptNull->base_sum);return false;}return true;}
3、消息编号检查
消息编号是从0开始的0~65535 的消息编号,每发一个消息,消息编号都加1,到了65535就从0开始。
bool gateway_session::checkMsgIndex(uint16 msgIndex){if(msg_index != msgIndex)//消息编号不正确的直接返回错误{return false;}if(msg_index == 0xffff)//到达65535的重新从0开始{msg_index = 0;}else{msg_index++;//严格递增}return true;}
0 0
- 游戏服务器之消息校验
- 游戏服务器之角色消息列表
- 游戏服务器之场景和网关之间的消息同步
- 游戏服务器之中心服务器
- 游戏服务器之服务器对象
- 游戏服务器之锁
- 游戏服务器之ai
- 游戏服务器之副本
- 游戏服务器之技能
- 游戏服务器之网关
- 游戏服务器之登录
- 游戏服务器之加密
- 小议游戏服务器的消息组包
- MMORPG 游戏服务器消息定义与规范
- 小议游戏服务器的消息组包
- 快速多人游戏(2) - 客户端预测和服务器校验
- 快速多人游戏(2) - 客户端预测和服务器校验
- 游戏服务器之文件数据库
- 在android系统中开发DLNA
- 笔记17--ListView添加滑动删除
- 浅谈Linux的内存管理机制
- C++常见输入输出小结
- POJ 3617 Best Cow Line
- 游戏服务器之消息校验
- Tkinter中button按钮未按却主动执行command函数问题
- Android下DLNA和UPnP的研究以及问题
- CCS5.5 CMD文件小结
- ACM hdu 1019 Least Common Multiple
- 运算符重载
- ndk-stack定位crash
- JBPM4.4总结(一)——基础知识
- POJ2184