这一部分需要向大家介绍的是服务器的select以及收发包的具体流程,从核心代码功能上分析网络交互具体过程。

  首先大家要看第二部分(part2 of net)的代码结构图,因为在接下来的流程过程中会用到其中模块的名称,若是不知道大致的功能那么接下来的解说可能就成为天书了。

  总体流程为:服务器管理器初始化并创建主套接字连接,进入主循环等待新连接(select),如果有新的连接则将新连接加入连接管理器。不管有没有新的连接,循环会依次处理连接的异常->输入流->输出流->命令处理。其中异常即连接包发送错误的处理,输入流即套接字输入流中如果大小长度不为空则重新拼接包,输出流进行包的拼接,并将未发送的流进行发送,命令处理其实是对输入流的处理,处理(handler)发送过来的包。

  以下详细说明这几个流程从代码上的实现,以及所在的模块。

  1、  服务器管理器初始化(servermanager)

bool ServerManager::init() {__ENTER_FUNCTIONserversocket_ = new pap_server_common_net::Socket(g_config.billing_info_.port_);Assert(serversocket_);serversocket_->set_nonblocking();socketid_ = serversocket_->getid(); Assert(socketid_ != SOCKET_INVALID); FD_SET(socketid_, &readfds_[kSelectFull]); FD_SET(socketid_, &exceptfds_[kSelectFull]); minfd_ = maxfd_ = socketid_; timeout_[kSelectFull].tv_sec = 0; timeout_[kSelectFull].tv_usec = 0; threadid_ = pap_common_sys::get_current_thread_id(); uint16_t i; for (i = 0; i < OVER_SERVER_MAX; ++i) { serverhash_[i] = ID_INVALID; } return true; __LEAVE_FUNCTION return false; }

  2、  服务器管理器进入主循环(servermanager)

void ServerManager::loop() {__ENTER_FUNCTIONwhile (isactive()) {bool result = false; try { result = select(); Assert(result); //ERRORPRINTF("select"); result = processexception(); Assert(result); //ERRORPRINTF("processexception"); result = processinput(); Assert(result); //ERRORPRINTF("processinput"); result = processoutput(); Assert(result); //ERRORPRINTF("processoutput");  } catch(...) { } try { result = processcommand(); Assert(result); //ERRORPRINTF("processcommand");  } catch(...) { } try { result = heartbeat(); Assert(result); } catch(...) { } } __LEAVE_FUNCTION }

loop

  3、  服务器线程进入select模式

bool ServerManager::select() {__ENTER_FUNCTIONtimeout_[kSelectUse].tv_sec = timeout_[kSelectFull].tv_sec;timeout_[kSelectUse].tv_usec = timeout_[kSelectFull].tv_usec;readfds_[kSelectUse] = readfds_[kSelectFull]; writefds_[kSelectUse] = writefds_[kSelectFull]; exceptfds_[kSelectUse] = exceptfds_[kSelectFull]; pap_common_base::util::sleep(100); int32_t result = SOCKET_ERROR; try { result = pap_common_net::socket::Base::select( maxfd_ + 1, &readfds_[kSelectUse], &writefds_[kSelectUse], &exceptfds_[kSelectUse], &timeout_[kSelectUse]); Assert(result != SOCKET_ERROR); } catch(...) { g_log->fast_save_log(kBillingLogFile, "ServerManager::select have error, result: %d", result); } return true; __LEAVE_FUNCTION return false; }

select

  4、  服务器线程进行异常处理

bool ServerManager::processexception() {__ENTER_FUNCTIONif (SOCKET_INVALID == minfd_ && SOCKET_INVALID == maxfd_)return true; uint16_t connectioncount = billingconnection::Manager::getcount(); billingconnection::Server* serverconnection = NULL; uint16_t i; for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) { Assert(false); continue; } if (FD_ISSET(socketid, &exceptfds_[kSelectUse])) { removeconnection(serverconnection); } } return true; __LEAVE_FUNCTION return false; }

processexception

  5、  服务器线程进行输入流处理

bool ServerManager::processinput() {__ENTER_FUNCTIONif (SOCKET_INVALID == minfd_ && SOCKET_INVALID == maxfd_)return true; //no connection  uint16_t i; if (FD_ISSET(socketid_, &readfds_[kSelectUse])) { for (i = 0; i < kOneStepAccept; ++i) { if (!accept_newconnection()) break; } } uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (FD_ISSET(socketid, &readfds_[kSelectUse])) { //read information if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { try { if (!serverconnection->processinput()) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } } return true; __LEAVE_FUNCTION return false; }

processinput

  6、  服务器线程进行输出流处理

bool ServerManager::processoutput() {__ENTER_FUNCTIONif (SOCKET_INVALID == maxfd_&& SOCKET_INVALID == minfd_)return false; uint16_t i; uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (FD_ISSET(socketid, &writefds_[kSelectUse])) { if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { try { if (!serverconnection->processoutput()) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } } return true; __LEAVE_FUNCTION return false; }

processoutput

  7、  服务器线程进行命令处理

bool ServerManager::processcommand() {__ENTER_FUNCTIONif (SOCKET_INVALID == maxfd_&& SOCKET_INVALID == minfd_)return false; uint16_t i; uint16_t connectioncount = billingconnection::Manager::getcount(); for (i = 0; i < connectioncount; ++i) { if (ID_INVALID == connectionids_[i]) continue; billingconnection::Server* serverconnection = NULL; serverconnection = g_connectionpool->get(connectionids_[i]); //serverconnection = &billing_serverconnection_;  Assert(serverconnection); int32_t socketid = serverconnection->getsocket()->getid(); if (socketid_ == socketid) continue; if (serverconnection->getsocket()->iserror()) { removeconnection(serverconnection); } else { //connection is ok try { if (!serverconnection->processcommand(false)) removeconnection(serverconnection); } catch(...) { removeconnection(serverconnection); } } } return true; __LEAVE_FUNCTION return false; }

processcommand

  下一部分,我将讲解在网络部分一些重要的代码块。

转载于:https://www.cnblogs.com/liuzhi/p/4084565.html

MMORPG大型游戏设计与开发(part3 of net)相关推荐

  1. MMORPG大型游戏设计与开发(服务器 游戏场景 地图和区域)

    地图的数据以及区域的信息是场景的重要组成部分,这些数据同时存在客户端和服务器,而且都是由编辑器生成的.那么保存的文件数据结构是怎样的?一张3D的场景地图又是怎样处理这些数据的?同时告诉大家这里同样只是 ...

  2. MMORPG大型游戏设计与开发(服务器 游戏场景 动态场景与副本)

    场景的内容讲解到今天算是暂时划上一个句号了,接下来为大家讲解的是AI部分(大型AI),如果有兴趣的朋友不妨持续关注这些文章,大家一起学习和进步.动态场景和副本是场景中特殊的类型,副本在这里想必已经是无 ...

  3. MMORPG大型游戏设计与开发(part5 of net)

    上一部分将服务器的具体代码的实现介绍给了大家,想必大家也了解到了服务器处理一次消息的复杂度.如果大家能够将各个过程掌握清楚,就会发觉其实整个逻辑与交互过程是比较清晰的.那么服务器与服务器之间的通讯,其 ...

  4. 百万在线:大型游戏服务端开发

    进入手游时代,服务端技术也在向前演进.现代游戏服务端既要承载数以万计的在线玩家,又要适应快速变化的市场需求,因此,如何设计合适的架构就成了重中之重.服务端技术并不简单,作为服务端新人,全面掌握服务端技 ...

  5. 基于android的2048游戏设计,基于Android平台的2048游戏设计与开发.docx

    基于Android平台的2048游戏设计与开发 高级操作系统论文(设计) 题 目 基于Android个人2048 小游戏的设计与开发姓 名 学 号 院. 系 信息学院 专 业 指导教师 职称(学历)目 ...

  6. 《基于Unity的2D多人乱斗闯关游戏设计与开发》--小组博客综述

    文章目录 项目名称 项目背景 项目简介 项目架构 项目特色 大致功能需求 游戏模式/内容 项目技术选型 项目分工 项目具体计划 此次项目实训不完全按照项目计划书进行,因为游戏范围太广,可能随时调整游戏 ...

  7. 基于Java多线程的打怪升级类游戏设计与开发

    摘要:本文论述了通过JAVA多线程.基于JAVA Swing的GUI图形用户界面设计.IO输入输出流.JDBC技术,实现了游戏系统的UI设计.游戏数据的存储.关卡的设置.用户头像的上传与更改.游戏数据 ...

  8. java俄罗斯方块ppt_基于Java俄罗斯方块游戏设计与开发PPT.ppt

    基于Java俄罗斯方块游戏设计与开发PPT 基于Java的俄罗斯方块游戏的设计与实现 答 辩 人:xxx 学 号:201012120201 指导老师:xxx副教授 专 业:网络工程 学 院:信息科学与 ...

  9. 游戏设计与开发_独立游戏开发:怎样设计游戏新手教学?

    教你画像素画原创出品 塞尔达荒野之息 1.游戏新手教学需要考虑的4个问题 1.玩家怎么玩? 2.玩家怎么完成游戏目标? 3.为什么玩家要这么做? 4.玩家何时会采取行动? 动作类游戏,玩家的操作会即时 ...

最新文章

  1. 祝我亲爱的天蝎GG生日快乐!+相识3周年小纪念
  2. 飞书,成就组织和个人 让每一分努力都有意义!
  3. java实现迷宫算法--转
  4. 计算机在能源领域的应用,计算机在能源中的应用
  5. 《可穿戴创意设计:技术与时尚的融合》一一3.3 纺织与教育
  6. Java Web 前端高性能优化(二) 1
  7. django 1.8 官方文档翻译: 3-2-3 TemplateResponse 和 SimpleTemplateResponse
  8. win10+jdk8重启后失效
  9. python的遍历循环语句for、不能遍历的数据类型是_14、python循环遍历 for 语法
  10. 一张模板替代数百Excel,这个工具让报表工作自动进行
  11. 2022道路运输企业安全生产管理人员考试题及答案
  12. 单端正激(Forward)变换器的工作原理CCM模式下电路设计参数计算
  13. SAP Scripting Tracker基本使用技巧
  14. Mac 共享WiFi给任意设备(Android,Iphone等等)
  15. 前端后台管理系统————01版权限开发(附带教程及代码)
  16. Git 分支合并情况
  17. Unity3D引擎之渲染技术系列
  18. 中国人工智能市场运营调研及发展前景预测报告2022-2028年
  19. idown v1.3.0build 130
  20. 在Excel每个表单的相同位置插入相同数据

热门文章

  1. python里compile的作用_Python代码中compile()函数具有哪些功能呢?
  2. JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven
  3. Linux下Git和GitHub使用方法总结(Ubuntu16.04)
  4. spss主成分综合得分_【SPSS因子分析】在SPSS中对医学多个数值变量进行因子分析 —【杏花开医学统计】...
  5. gtk 控件内存回收_咱们从头到尾说一次 Java 垃圾回收
  6. 杂项:高考填报志愿综合参考系统
  7. 玩转u8g2 OLED库,一篇就够
  8. shp系列(六)——利用C++进行Dbf文件的写(创建)
  9. hdu4035 Maze 【期望dp + 数学】
  10. STC89C52RC内部EEPROM编程