当前位置: 首页 > news >正文

社区智慧警务网站如何推进警务室建设方案wordpress 隐形按钮

社区智慧警务网站如何推进警务室建设方案,wordpress 隐形按钮,wordpress加载模板文件路径,wordpress文章存储位置文章目录 1 项目总体架构2 项目需求2.1 服务器职责2.2 消息的格式和定义 3 基于Tcp连接的通信方式3.1 通道层实现GameChannel类3.1.1 TcpChannel类3.1.2 Tcp工厂类3.1.3 创建主函数#xff0c;添加Tcp的监听套接字3.1.4 代码测试 3.2 协议层与消息类3.2.1 消息的定义3.2.2 消息… 文章目录 1 项目总体架构2 项目需求2.1 服务器职责2.2 消息的格式和定义 3 基于Tcp连接的通信方式3.1 通道层实现GameChannel类3.1.1 TcpChannel类3.1.2 Tcp工厂类3.1.3 创建主函数添加Tcp的监听套接字3.1.4 代码测试 3.2 协议层与消息类3.2.1 消息的定义3.2.2 消息类-用户请求对象的创建3.2.3 protoc消息的创建3.2.4 消息对象的构造与解析3.2.5 代码测试-13.2.6 报文里的多条请求3.2.7 Tcp报文粘包的处理3.2.8 数据包代码测试3.2.8.1 完整数据3.2.8.2 数据缺失和错误 3.2.9 协议和通道相互绑定3.2.9.1 循环引用的问题3.2.9.1 相互绑定的实现3.2.9.3 代码测试 3.3 业务层玩家类的创建3.3.1 在Role中绑定协议3.3.2 在协议中绑定一个role3.3.3 在tcp中绑定协议和玩家对象3.3.4 重写协议层获取角色处理对象3.3.5 修改角色Init函数3.3.6 测试代码 1 项目总体架构 2 项目需求 2.1 服务器职责 服务器职责接收客户端数据发送数据给客户端 新客户端连接后向其发送ID和名称新客户端连接后向其发送周围玩家的位置新客户端连接后向周围玩家发送其位置收到客户端的移动信息后向周围玩家发送其新位置收到客户端的移动信息后向其发送周围新玩家位置收到客户端的聊天信息后向所有玩家发送聊天内容客户端断开时向周围玩家发送其断开的消息 2.2 消息的格式和定义 消息定义 每一条服务器和客户端之前的消息都应该满足以下格式 消息内容的长度4个字节低字节在前| 消息ID4个字节低字节在前| 消息内容 | 消息以及其处理方式已经在客户端实现本项目要实现的是服务器端的相关处理 详细定义如下 消息ID消息内容发送方向客户端处理服务器处理1玩家ID和玩家姓名S-C记录自己ID和姓名无2聊天内容C-S无广播给所有玩家3新位置C-S无处理玩家位置更新后的信息同步200玩家ID聊天内容/初始位置/动作预留/新位置S-C根据子类型不通而不同无201玩家ID和玩家姓名S-C把该ID的玩家从画面中拿掉无202周围玩家们的位置S-C在画面中显示周围的玩家无 3 基于Tcp连接的通信方式 3.1 通道层实现GameChannel类 GameChannel::GetInputNextStage 函数中直接返回成员变量中的协议对象GameChannel 的析构函数中要一并从kernel中摘掉协议对象玩家对象并析构之GameChannelFac::CreateTcpDataChannel 函数要一并创建通道对象协议对象玩家对象并将这三者绑定起来添加到kernel中 3.1.1 TcpChannel类 使用框架提供的Tcp通信类创建GameChannel类继承ZinxTcpData重写GetInputNextStage函数将tcp收到的数据交给协议对象解析 每个协议对象只处理本通道的协议数据 GameProtocol* m_proto NULL; 创建对象啊以后交给m_proto通过该变量访问通道内的数据 AZinxHandler* GameChannel::GetInputNextStage(BytesMsg _oInput) {return m_proto; }3.1.2 Tcp工厂类 创建GameChannelFac类用于创建基于连接的GameChannel对象因为玩家是通过tcp连接所以tcp通道协议对象和玩家对象是一对一对一的绑定关系创建通道的时候需要创建协议并且绑定协议对象 ZinxTcpData* GameConnFact::CreateTcpDataChannel(int _fd) { /*创建tcp通道对象*/auto pChannel new GameChannel(_fd); /*创建协议对象*/auto pProtocol new GameProtocol(); /*绑定协议对象*/pChannel-m_proto pProtocol; /*将协议对象添加到kernel, 注意参数需要为指针*/ZinxKernel::Zinx_Add_Proto(*pProtocol);return pChannel; } 3.1.3 创建主函数添加Tcp的监听套接字 #include GameChannel.hint main() {ZinxKernel::ZinxKernelInit();/*添加监听通道需要端口号和连接*/ZinxKernel::Zinx_Add_Channel(*(new ZinxTCPListen(8899, new GameConnFact())));ZinxKernel::Zinx_Run();ZinxKernel::ZinxKernelFini(); }3.1.4 代码测试 设置标准输入 UserData* GameProtocol::raw2request(std::string _szInput) {cout _szInput endl;return nullptr; }3.2 协议层与消息类 GameProtocol::GetMsgProcessor 函数即返回绑定的玩家对象GameProtocol::GetMsgSender 函数即返回绑定的通道对象GameProtocol::response2raw 函数要返回消息内容编码后的字节流将GameMsg 对象中每个消息对象序列化并结合长度消息ID一起粘合起来GameProtocol::raw2request 函数要将一串tcp数据流转换成游戏消息 3.2.1 消息的定义 //h enum MSG_TYPE {MSG_TYPE_LOGIN_ID_NAME 1,MSG_TYPE_CHAT_CONTENT 2,MSG_TYPE_NEW_POSTION 3,MSG_TYPE_BROADCAST 200,MSG_TYPE_LOGOFF_ID_NAME 201,MSG_TYPE_SRD_POSTION 202 } enMsgType;3.2.2 消息类-用户请求对象的创建 一个类一个请求 //h class GameMsg :public UserData { public:/*用户的请求信息*/google::protobuf::Message * pMsg NULL;enum MSG_TYPE {MSG_TYPE_LOGIN_ID_NAME 1,MSG_TYPE_CHAT_CONTENT 2,MSG_TYPE_NEW_POSTION 3,MSG_TYPE_BROADCAST 200,MSG_TYPE_LOGOFF_ID_NAME 201,MSG_TYPE_SRD_POSTION 202} enMsgType;/*已知消息内容创建消息对象*/GameMsg(MSG_TYPE _type, google::protobuf::Message * _pMsg);/*将字节流内容转换成消息结构*/GameMsg(MSG_TYPE _type, std::string _stream);/*序列化本消息*/std::string serialize();virtual ~GameMsg(); };一个消息类里应该要放多条请求每个请求一条消息 class MultiMsg :public UserData { public:std::listGameMsg * m_Msgs; }; 3.2.3 protoc消息的创建 protoc msg.proto --cpp_out./syntaxproto3; package pb;//无关选项用于客户端 option csharp_namespacePb;message SyncPid{int32 Pid1;string Username2; }message Player{int32 Pid1;Position P2;string Username3; }message SyncPlayers{/*嵌套多个子消息类型Player的消息*/repeated Player ps1; }message Position{float X1;float Y2; float Z3; float V4;int32 BloodValue5; }message MovePackage{Position P1;int32 ActionData2; }message BroadCast{int32 Pid1;int32 Tp2;/*根据Tp不同Broadcast消息会包含聊天内容(Content)或初始位置(P)或新位置P*/oneof Data{string Content3;Position P4;/*ActionData暂时预留*/int32 ActionData5;}string Username6; }message Talk{string Content1; } 3.2.4 消息对象的构造与解析 GameMsg::GameMsg(MSG_TYPE _type, std::string _stream) :enMsgType(_type) {/*通过简单工厂构造具体的消息对象*/switch (_type){case GameMsg::MSG_TYPE_LOGIN_ID_NAME:pMsg new pb::SyncPid();break;case GameMsg::MSG_TYPE_CHAT_CONTENT:pMsg new pb::Talk();break;case GameMsg::MSG_TYPE_NEW_POSTION:pMsg new pb::Position();break;case GameMsg::MSG_TYPE_BROADCAST:pMsg new pb::BroadCast();break;case GameMsg::MSG_TYPE_LOGOFF_ID_NAME:pMsg new pb::SyncPid();break;case GameMsg::MSG_TYPE_SRD_POSTION:pMsg new pb::SyncPlayers();break;default:break;}/*将参数解析成消息对象内容*/pMsg-ParseFromString(_stream); }std::string GameMsg::serialize() {std::string ret;pMsg-SerializeToString(ret);return ret; } 3.2.5 代码测试-1 3.2.6 报文里的多条请求 //h class MultiMsg :public UserData { public:std::listGameMsg* m_Msgs; //注意此处要加命名空间 };MultiMsg* pRet new MultiMsg(); //此时没有用户请求/*构造一条用户请求*/GameMsg* pMsg new GameMsg((GameMsg::MSG_TYPE)id, szLast.substr(8, iLength)); // iLength是正文的长度pRet-m_Msgs.push_back(pMsg);//Debug打印每条请求for (auto single : pRet-m_Msgs){cout single-pMsg-Utf8DebugString() endl;}3.2.7 Tcp报文粘包的处理 问题tcp或类似的流式文件无法保证收到的数据按照期望的格式分割。 举例服务器期望接收2个字节的数据作为一个合理请求。客户端发送了两个请求四个字节后由于网络拥塞服务器收到了1个字节后recv返回1秒钟后数据到来再次调用recv会收到3个字节。 常规套路 设定报文边界一般使用Tag Length Value的格式recv数据后若接收缓冲区当前数据长度小于报文内规定长度则保留当前缓冲区下次recv数据后重新处理缓存若接收缓冲区数据长度大于等于报文内规定长度则循环生成生成请求并保留后续多余的数据等待下次recv数据后重新处理滑窗 UserData* GameProtocol::raw2request(std::string _szInput) {MultiMsg* pRet new MultiMsg(); //此时没有用户请求szLast.append(_szInput);while (1){if (szLast.size() 8){break;}/*在前四个字节中读取消息内容长度*/int iLength 0;iLength | szLast[0] 0;iLength | szLast[1] 8;iLength | szLast[2] 16;iLength | szLast[3] 24;/*中四个字节读类型id*/int id 0;id | szLast[4] 0;id | szLast[5] 8;id | szLast[6] 16;id | szLast[7] 24;/*通过读到的长度判断后续报文是否合法*/if (szLast.size() - 8 iLength){/*本条报文还没够啥都不干*/break;}/*构造一条用户请求*/GameMsg* pMsg new GameMsg((GameMsg::MSG_TYPE)id, szLast.substr(8, iLength)); // iLength是正文的长度pRet-m_Msgs.push_back(pMsg);/*弹出已经处理成功的报文*/szLast.erase(0, 8 iLength);}//Debug打印每条请求for (auto single : pRet-m_Msgs){cout single-pMsg-Utf8DebugString() endl;}return pRet; }/*参数来自业务层待发送的消息 返回值转换后的字节流*/ std::string * GameProtocol::response2raw(UserData _oUserData) {int iLength 0;int id 0;std::string MsgContent;GET_REF2DATA(GameMsg, oOutput, _oUserData);id oOutput.enMsgType;MsgContent oOutput.serialize();iLength MsgContent.size();auto pret new std::string();pret-push_back((iLength 0) 0xff);pret-push_back((iLength 8) 0xff);pret-push_back((iLength 16) 0xff);pret-push_back((iLength 24) 0xff);pret-push_back((id 0) 0xff);pret-push_back((id 8) 0xff);pret-push_back((id 16) 0xff);pret-push_back((id 24) 0xff);pret-append(MsgContent);return pret; }3.2.8 数据包代码测试 3.2.8.1 完整数据 0800000001000000080112047465737408 00 00 00 - 前4个字节存储数据消息的长度变量值是数据消息的长度为8个字节。 01 00 00 00 - 第5-8个字节存储的是用户的ID变量值表示用户ID是1 08 01 12 04 74 65 73 74 - 末尾8个字节表示数据消息的全部内容 3.2.8.2 数据缺失和错误 收到数据以后啥都不干 3.2.9 协议和通道相互绑定 3.2.9.1 循环引用的问题 一般地来说不涉及使用类的成员的时候尽量避免使用头文件直接声明一个类即可。 在GameChannel.h中引用了头文件GameProtocol.h #pragma once #includeZinxTCP.h #includeGameProtocol.hclass GameChannel :public ZinxTcpData { public:GameChannel(int _fd);virtual ~GameChannel();GameProtocol * m_proto NULL; };如果在GameProtocol.h中引用GameChannel.h则会造成循环引用。 处理办法是直接在前面声明相关的类。 #pragma once #include zinx.hclass GameChannel; //避免循环引用class GameProtocol :public Iprotocol {std::string szLast; //上次未来得及处理的报文 public:GameChannel* m_channel NULL;GameProtocol() ;virtual ~GameProtocol(); };3.2.9.1 相互绑定的实现 3.2.9.3 代码测试 pb::SyncPid* pmsg new pb::SyncPid();pmsg-set_pid(1);pmsg-set_username(test);GameMsg gm(GameMsg::MSG_TYPE_LOGIN_ID_NAME, pmsg);auto output gm.serialize();for (auto byte : output){printf(%02X , byte);}puts();char buff[] { 0x08, 0x01, 0x12, 0x04 ,0x74, 0x65, 0x73, 0x74 };std::string input(buff, sizeof(buff));auto ingm GameMsg(GameMsg::MSG_TYPE_LOGIN_ID_NAME, input);std::cout dynamic_castpb::SyncPid* (ingm.pMsg)-pid() std::endl;std::cout dynamic_castpb::SyncPid* (ingm.pMsg)-username() std::endl; 收到数据 07 00 00 00 02 00 00 00 0A 05 68 65 6C 6C 6F07 00 00 00 - 数据消息的长度是7个字节 02 00 00 00 - 消息ID是2 0A 05 68 65 6C 6C 6F - 转换成string代表hello 3.3 业务层玩家类的创建 3.3.1 在Role中绑定协议 class GameProtocol;class GameRole :public Irole { public:GameRole() ;virtual ~GameRole();// 通过 Irole 继承virtual bool Init() override;virtual UserData* ProcMsg(UserData _poUserData) override;virtual void Fini() override;GameProtocol* m_pProto NULL; };3.3.2 在协议中绑定一个role class GameChannel; //避免循环引用 class GameRole; class GameProtocol :public Iprotocol {std::string szLast; //上次未来得及处理的报文 public:GameChannel* m_channel NULL;GameRole* m_Role NULL;GameProtocol() ;virtual ~GameProtocol();// 通过 Iprotocol 继承virtual UserData* raw2request(std::string _szInput) override;virtual std::string* response2raw(UserData _oUserData) override;virtual Irole* GetMsgProcessor(UserDataMsg _oUserDataMsg) override;virtual Ichannel* GetMsgSender(BytesMsg _oBytes) override; }; 3.3.3 在tcp中绑定协议和玩家对象 ZinxTcpData* GameConnFact::CreateTcpDataChannel(int _fd) { /*创建tcp通道对象*/auto pChannel new GameChannel(_fd); /*创建协议对象*/auto pProtocol new GameProtocol();/*创建玩家对象*/auto pRole new GameRole();/*绑定协议对象和通道对象*/pChannel-m_proto pProtocol;pProtocol-m_channel pChannel;/*绑定协议对象和玩家对象*/pProtocol-m_Role pRole;pRole-m_pProto pProtocol;/*将协议对象添加到kernel, 注意参数需要为指针*/ZinxKernel::Zinx_Add_Proto(*pProtocol);/*将玩家对象添加到kernel*/ZinxKernel::Zinx_Add_Role(*pRole);return pChannel; }3.3.4 重写协议层获取角色处理对象 Irole* GameProtocol::GetMsgProcessor(UserDataMsg _oUserDataMsg) {return m_Role; }3.3.5 修改角色Init函数 bool GameRole::Init() {return true; }3.3.6 测试代码 /*处理游戏相关的用户请求*/ UserData* GameRole::ProcMsg(UserData _poUserData) {/*测试打印消息内容*/GET_REF2DATA(MultiMsg, input, _poUserData);for (auto single : input.m_Msgs){cout type is single-enMsgType endl;cout single-pMsg-Utf8DebugString() endl;}return nullptr; 08000000010000000801120474657374
http://www.w-s-a.com/news/925966/

相关文章:

  • 开源 网站开发框架哪些网站可以做图片链接
  • 大良制作网站网站设计的能力要求
  • 前端设计除了做网站还能做什么江苏高校品牌专业建设工程网站
  • 做二手房产网站多少钱用户权限配置wordpress
  • 做亚马逊网站需要租办公室吗小型企业网站模板
  • 网站全屏视频怎么做个人公司注册网上申请
  • 如何k掉别人的网站搜索引擎优化与关键词的关系
  • 百度推广 网站吸引力做网站开发的薪酬怎么样
  • js网站开发工具软件营销方案
  • 做网站的天空网云南省建设厅网站怎么进不去
  • 天津网站排名提升网络营销推广策略包括哪些
  • 网站建设与管理 ppt网站打开是别人的
  • 图片网站怎么做排名怎么分析一个网站seo
  • 伪原创对网站的影响深圳装修公司排名100强
  • 网站建设公司效果个人可以做医疗信息网站吗
  • 网站使用arial字体下载微网站 建设
  • 文化馆网站建设意义营销型国外网站
  • 公司网站定位建议wordpress怎么用模板
  • 中国十大热门网站排名计算机选什么专业最好
  • 怀化建设企业网站太原网站关键词排名
  • 空间注册网站网站制作是怎么做的
  • 数码家电商城网站源码一个网站的成本
  • 网站伪静态是什么意思麻涌东莞网站建设
  • 理县网站建设公司郑州仿站定制模板建站
  • 手机网站建设网站报价诸城人才网招聘网
  • 一起做网站怎么下单临沂网站制作
  • 公司网站案例企业网站 模版
  • 做的好的响应式网站有哪些网站界面设计案例
  • 上海创意型网站建设icp备案网站信息
  • 网站没收录中山手机网站制作哪家好