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

天津网站建设普斯泰python在线编程题库

天津网站建设普斯泰,python在线编程题库,树苗网站源码,临汾尚世互联网站建设文章目录 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… 文章目录 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 代码测试 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类 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 消息类的结构设计和实现 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报文粘包的处理 添加数据头4ID4数据信息 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 完整数据 08 00 00 00 01 00 00 00 08 01 12 04 74 65 73 7408 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 代码测试 收到数据 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
http://wiki.neutronadmin.com/news/308614/

相关文章:

  • 企业名录是什么重庆百度快照优化排名
  • 个人网站有哪些站北京网站建设公司司
  • wordpress老站开启多站点品牌网站建设4a小蝌蚪
  • 寻花问柳一家专门做男人的网站嘉兴小程序开发公司
  • 上海网站建设报价书wordpress tag 404
  • 北京网站建设报价表店面设计费用
  • 网站建设客户需求分析长沙学校网站建设
  • 柳州做网站的公司有哪些电脑软件推广联盟
  • 广东微信网站制作公司软件开发项目流程
  • 都哪些网站可以做gif网站公司怎么做运营
  • 北京论坛网站建设有了域名搭建网站详细步骤
  • 广东融都建设有限公司 公司网站nodejs适合网站开发
  • 360平台怎么做网站优化电脑软件开发是什么专业
  • 百度新闻源网站公司网站app怎么做
  • 做影视网站什么cms好用wordpress 安装主题 主机名
  • 网站建设试卷摄影东营新闻最新消息
  • phpcms 手机网站模板杭州建设网点地址查询
  • 网站手机版跳转 seo微信公众号的微网站怎么做
  • 黑龙江省建设厅网站站长鞍山网站制作谁家好
  • 虚拟主机WordPress建站企业网站推广阶段
  • 营销型网站的设计步骤网站空间租用哪家好
  • 万网主机建设网站流程首饰行业网站建设策划
  • 移动网站开发培训英文建站
  • 医院网站案例郑州比较厉害的短视频公司
  • 网站 风格设计工作室网站
  • 福建龙岩网站制作公司培训网站计时怎么破
  • 网站建设中界面模板下载江苏省住房城乡建设厅门户网站
  • 网站英文域名怎么查建筑人才网证书
  • 企业网站建设及前期准备找别人做网站注意什么
  • 贵州做网站怎么推广山东省作风建设网站