不知不觉又是三周过去了。

这几周忙了一下,其他时间全都在搞服务端,简直是酸爽的不行。。。不过还好出了些成果。

目前服务端有:

1、版本服务:游戏版本更新

2、账号服务:用户身份验证,返回各种连接(代理服务、聊天服务)

3、代理服务:获取游服列表、获取游服状态(是否需要排队)、进入游戏的验证、游服数据转发

4、队列服务:处理排队队列中用户的队列情况变化,并广播(本来这个是放在代理服务器上做的,但是我觉得广播起来有点恶心就分出来了,看起来各个服务的功能也清晰些)

5、游戏服务:游戏业务逻辑处理(作为1-n个特殊的客户端连接到代理服务器)

6、聊天服务

客户端方面,优化了一些网络通讯方面的代码,把各种消息重新整理了一遍。界面表现方面几乎没动过。

整个框架基本上实现了登录、选服、排队(等待、结束)、进入游戏、聊天。

想了一下,还是放段代码。

  1. unit gate.handler;
  2.  
  3. interface
  4.  
  5. uses
  6. System.SysUtils, System.Classes, System.Math, diocp_coder_tcpServer,
  7. diocp_tcp_server, fol.msgcode, fol.types, fol.simpleMsgPack,
  8. fol.server.types, fol.server.session, gate.session, gate.cache;
  9.  
  10. procedure pushMsgData(pvMsgData: TSimpleMsgPack; pvContext: TIocpClientContext);
  11. procedure execHeart(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext);
  12. procedure execOffline(pvContext: TIOCPCoderClientContext);
  13.  
  14. function execRequest(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  15. function execRegister(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  16. function execRegisterGameServiceClient(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): string;
  17. function execRequestServerList(pvMsgData: TSimpleMsgPack): Integer;
  18. function execRequestServerState(const pvServerID: Integer; pvMsgData: TSimpleMsgPack): Integer;
  19. function execRequestStartGame(const pvServerID,pvUserID: Integer;
  20. pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  21. function execRequestGameService(pvMsgData: TSimpleMsgPack): Integer;
  22. function execTranspond(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  23.  
  24. implementation
  25.  
  26. uses utils_safeLogger;
  27.  
  28. procedure pushMsgData(pvMsgData: TSimpleMsgPack; pvContext: TIocpClientContext);
  29. var
  30. lvStream: TMemoryStream;
  31. begin
  32. lvStream:= TMemoryStream.Create;
  33. try
  34. if Assigned(pvContext) then
  35. begin
  36. pvMsgData.Add('result',MSG_RESULT_Success);
  37. pvMsgData.EncodeToStream(lvStream);
  38. lvStream.Position:= ;
  39. TIOCPCoderClientContext(pvContext).WriteObject(lvStream);
  40. end;
  41. finally
  42. lvStream.Free;
  43. end;
  44. end;
  45.  
  46. procedure execHeart(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext);
  47. begin
  48. if pvContext.LockContext('keeplive', nil) then
  49. try
  50. gvSessionManager.validChecked(pvContext);
  51. pvMsgData.Clear;
  52. finally
  53. pvContext.UnLockContext('keeplive', nil);
  54. end;
  55. end;
  56.  
  57. procedure execOffline(pvContext: TIOCPCoderClientContext);
  58. var
  59. lvServerID: Integer;
  60. lvUserID, lvServerKey: string;
  61. begin
  62. if pvContext.Data <> nil then
  63. begin
  64. {
  65. 1. 游戏客户端: 只是连接了代理服务器,并未选服登录游戏 (断开不需要处理)
  66. 2. 游戏客户端: 已经进入游戏的,断开需要更新对应服务器freenum
  67. 3. OM工具: 断开不需要处理
  68. 4. 游戏服务: 断开需要把游服记录删除(或者更新state)
  69. }
  70. lvServerID:= TClientSession(pvContext.Data).ServerID;
  71. lvUserID:= TClientSession(pvContext.Data).SessionID;
  72. case TClientSession(pvContext.Data).ClientType of
  73. tfctGameClient:
  74. begin
  75. sfLogger.logMessage('[INFO]: Client offline, serverid='+inttostr(lvServerID));
  76. then exit;
  77. //更新freenum(freenum+1)
  78. sfLogger.logMessage('[INFO]: Client offline, userid='+lvUserID);
  79. lvServerKey:= Format('server:%.3d',[lvServerID]);
  80. redisClient.HINCRBY(lvServerKey,);
  81. //kickOut这个session(或者设置为无效session)
  82. gvSessionManager.kickOutGameClient(lvUserID);
  83. end;
  84. tfctGameServiceClient:
  85. begin
  86. //更新游服列表
  87. lvServerKey:= Format('server:%.3d',[StrToInt(lvUserID)]);
  88. redisClient.DEL([lvServerKey]);
  89. gvSessionManager.kickOutGameService(lvUserID);
  90. end;
  91. tfctOMClient:
  92. begin
  93. sfLogger.logMessage('[INFO]: OMClient offline');
  94. gvSessionManager.kickOutOMClient(lvUserID);
  95. end;
  96. end;
  97. end;
  98. end;
  99.  
  100. function execRegister(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  101. var
  102. lvClientType: Integer;
  103. lvSessionID: string;
  104. begin
  105. if pvContext.LockContext('register', nil) then
  106. try
  107. lvClientType:= pvMsgData.I['client_type'];
  108. case lvClientType of
  109. ord(tfctGameClient):
  110. lvSessionID:= gvSessionManager.takeAGameClientSession(pvContext, pvMsgData.S['client_id']);
  111. ord(tfctGameServiceClient):
  112. lvSessionID:= execRegisterGameServiceClient(pvMsgData, pvContext);
  113. ord(tfctOMClient):
  114. lvSessionID:= gvSessionManager.takeAOMClientSession(pvContext, pvMsgData.S['client_id']);
  115. end;
  116. pvMsgData.Clear;
  117. pvMsgData.S['token']:= '(gate)token_'+lvSessionID;
  118. result:= MSG_RESULT_Success;
  119. finally
  120. pvContext.UnLockContext('register', nil);
  121. end;
  122. end;
  123.  
  124. function execRegisterGameServiceClient(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): string;
  125. var
  126. lvServiceID, lvServiceName, lvServerKey, lvMaxConn: string;
  127. begin
  128. lvServiceID:= pvMsgData.S['client_id'];
  129. lvServiceName:= pvMsgData.S['client_name'];
  130. lvMaxConn:= pvMsgData.S['client_maxconn'];
  131. result:= gvSessionManager.takeAGameServiceSession(pvContext,lvServiceID);
  132.  
  133. //example: hmset server:001 name 五行之始 state 1 freenum 1000
  134. lvServerKey:= Format('server:%.3d',[StrToInt(lvServiceID)]);
  135. redisClient.HMSET(lvServerKey,[',lvMaxConn]);
  136. end;
  137.  
  138. function execRequest(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  139. var
  140. lvMsgcode, lvCallbackID, lvServerID, lvUserID: Integer;
  141. begin
  142. lvMsgcode:= pvMsgData.I['msg_code'];
  143. lvCallbackID:= pvMsgData.I['callbackid'];
  144. sfLogger.logMessage('[INFO]: Receive a message package, msgcode=' + inttostr(lvMsgcode));
  145. case lvMsgcode of
  146. MSG_NET_Register: result:= execRegister(pvMsgData, pvContext);
  147. MSG_NET_GetServerList:
  148. begin
  149. pvMsgData.Clear;
  150. result:= execRequestServerList(pvMsgData);
  151. end;
  152. MSG_NET_GetServerState:
  153. begin
  154. lvServerID:= pvMsgData.I['serverid'];
  155. pvMsgData.Clear;
  156. result:= execRequestServerState(lvServerID,pvMsgData);
  157. end;
  158. MSG_NET_StartGame:
  159. begin
  160. lvServerID:= pvMsgData.I['serverid'];
  161. lvUserID:= pvMsgData.I['userid'];
  162. pvMsgData.Clear;
  163. result:= execRequestStartGame(lvServerID,lvUserID,pvMsgData,pvContext);
  164. end;
  165. else
  166. begin
  167. execRequestGameService(pvMsgData);
  168. pvMsgData.Clear;
  169. exit;
  170. end;
  171. end;
  172. pvMsgData.Add('callbackid', lvCallbackID);
  173. end;
  174.  
  175. function execRequestServerList(pvMsgData: TSimpleMsgPack): Integer;
  176. var
  177. i: Integer;
  178. lvServerKey: string;
  179. lvData: TArray<string>;
  180. begin
  181. do
  182. begin
  183. lvServerKey:= Format('server:%.3d',[i]);
  184. lvData:= redisClient.HMGET(lvServerKey, ['name', 'state']);
  185. ) ]='') then break;
  186. pvMsgData.Add(lvData[], StrToInt(lvData[]));
  187. end;
  188. result:= MSG_RESULT_Success;
  189. end;
  190.  
  191. function execRequestServerState(const pvServerID: Integer; pvMsgData: TSimpleMsgPack): Integer;
  192. var
  193. lvServerKey: string;
  194. lvFreeNum: Integer;
  195. begin
  196. lvServerKey:= Format('server:%.3d',[pvServerID]);
  197. redisClient.HGET(lvServerKey,'freenum',lvFreeNum);
  198. case lvFreeNum of
  199. : result:= MSG_RESULT_Queue;
  200. -: raise exception.Create('invalid freenum.');
  201. else result:= MSG_RESULT_Success;
  202. end;
  203. end;
  204.  
  205. function execRequestStartGame(const pvServerID,pvUserID: Integer;
  206. pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  207. var
  208. lvServerKey, lvQueueKey: string;
  209. lvFreeNum, lvState: Integer;
  210. begin
  211. if pvContext.Data <> nil then
  212. begin
  213. lvServerKey:= Format('server:%.3d',[pvServerID]);
  214. redisClient.HGET(lvServerKey,'state',lvState);
  215. then raise Exception.Create('Service is Closed.');
  216. redisClient.HGET(lvServerKey,'freenum',lvFreeNum);
  217. then raise Exception.Create('Invalid request, free num is zero.');
  218. //
  219. TClientSession(pvContext.Data).ServerID:= pvServerID;
  220. TClientSession(pvContext.Data).State:= tusOnline;
  221. //更新freenum(freenum-1)
  222. lvFreeNum:= Max(lvFreeNum - ,);
  223. redisClient.HSET(lvServerKey,'freenum',lvFreeNum);
  224. //广播上线消息给好友
  225. end;
  226. result:= MSG_RESULT_Success;
  227. end;
  228.  
  229. function execRequestGameService(pvMsgData: TSimpleMsgPack): Integer;
  230. var
  231. lvServerID: string;
  232. lvContext: TIocpClientContext;
  233. begin
  234. lvServerID:= IntToStr(pvMsgData.I['serverid']);
  235. lvContext:= gvSessionManager.findGameServiceContext(lvServerID);
  236. pushMsgData(pvMsgData,lvContext);
  237. end;
  238.  
  239. function execTranspond(pvMsgData: TSimpleMsgPack; pvContext: TIOCPCoderClientContext): Integer;
  240. var
  241. lvUserID: string;
  242. lvContext: TIocpClientContext;
  243. begin
  244. lvUserID:= pvMsgData.S['userid'];
  245. lvContext:= gvSessionManager.findGameClientContext(lvUserID);
  246. pushMsgData(pvMsgData,lvContext);
  247. end;
  248.  
  249. end.

【FOL】第九周的更多相关文章

  1. 第九周 psp

    团队项目PSP 一:表格     C类型 C内容 S开始时间 E结束时间 I时间间隔 T净时间(mins) 预计花费时间(mins) 讨论 讨论用户界面 9:50 12:45 35 45 80 分析与 ...

  2. PSP第九周

    一.表格 C(分类) C(内容) S(开始时间) ST(结束时间) I(打断时间) △(净工作时间) 学习 UML 12:30 13:20 0 50 编码 编码 20:00 22:10 0 130 学 ...

  3. 20145213《Java程序设计》第九周学习总结

    20145213<Java程序设计>第九周学习总结 教材学习总结 "五一"假期过得太快,就像龙卷风.没有一点点防备,就与Java博客撞个满怀.在这个普天同庆的节日里,根 ...

  4. 20145304 Java第九周学习报告

    20145304<Java程序设计>第九周学习总结 教材学习内容总结 JDBC简介 JDBC全名Java DataBase Connectivity,是Java联机数据库的标准规范.定义了 ...

  5. 21045308刘昊阳 《Java程序设计》第九周学习总结

    21045308刘昊阳 <Java程序设计>第九周学习总结 教材学习内容总结 第16章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 数据库本身是个独立运行的应用程序 撰 ...

  6. 20145330第九周《Java学习笔记》

    20145330第九周<Java学习笔记> 第十六章 整合数据库 JDBC入门 数据库本身是个独立运行的应用程序 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JD ...

  7. 20145337 《Java程序设计》第九周学习总结

    20145337 <Java程序设计>第九周学习总结 教材学习内容总结 数据库本身是个独立运行的应用程序 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC可以 ...

  8. 20145211 《Java程序设计》第九周学习总结——垂死病中惊坐起

    教材学习内容总结 JDBC简介 JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行操作,开发人员无须接触底层数据库驱动程序的差异性 JDBC标准分为两个部分:J ...

  9. 《Java程序设计》第九周学习总结

    20145224 <Java程序设计>第九周学习总结 第十六章 整合数据库 JDBC入门 ·数据库本身是个独立运行的应用程序 ·撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的 ...

  10. 20145236 《Java程序设计》第九周学习总结

    20145236 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章 整合数据库 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API ...

随机推荐

  1. Linux初学 - head,tail,grep,sed,yum,find

    head 查看文件头部 -n 指定查看行数 默认10行 tail 查看文件尾部 n 指定查看行数 默认10行 Grep 命令 用法大全 . 参数: -I :忽略大小写 -c :打印匹配的行数 -l : ...

  2. 直接修改.NET程序集 LLBL Gen 2.x-4.x 许可授权方法研究

    做数据库开发,如果要用ORM,LLBL Gen是一款优秀的框架和工具,目前最新版本是4.0.同时也推出了Lite免费版本,与Visual Studio的Express版本一样, 免费,但是它仅仅只支持 ...

  3. 新浪微博SDK开发(2):上传图片的技术难点

    在微博模块中,有一个API是可以发表带一张图片的微博的,当然提交方式是POST.在封装的时候,可能会遇到一个难点——如何上传图片? 要POST微博的同时带有图片,POST的内容必须为MultiPart ...

  4. WPF/Silverlight 下的图片局部放大

    最近的项目中也要用到一个局部图片放大的功能,园子里面一搜,发现(菩提下的杨过)杨大侠已经实现了. 请参见这里:http://www.cnblogs.com/yjmyzz/archive/2009/12 ...

  5. Netty中的坑(下篇)

    其实这篇应该叫Netty实践,但是为了与前一篇名字保持一致,所以还是用一下坑这个名字吧. Netty是高性能Java NIO网络框架,在很多开源系统里都有她的身影,而在绝大多数互联网公司所实施的服务化 ...

  6. try,catch,throw-----C++

    1.try,catch,throw: try包含你要防护的代码 ,称为防护块. 防护块如果出现异常,会自动生成异常对象并抛出. catch捕捉特定的异常,并在其中进行适当处理. throw可以直接抛出 ...

  7. Deep learning:五十(Deconvolution Network简单理解)

    深度网络结构是由多个单层网络叠加而成的,而常见的单层网络按照编码解码情况可以分为下面3类: 既有encoder部分也有decoder部分:比如常见的RBM系列(由RBM可构成的DBM, DBN等),a ...

  8. [emacs] Drawing uml under emacs org-mode using plantUML - 类图

    [emacs] Drawing uml under emacs org-mode using plantUML - 类图 // */ // ]]>   [emacs] Drawing uml u ...

  9. android调试输出

    测试时不想直接debug总要调试输出一些字符串信息,那以下方法可选: 1.用Log.i(TAG, "onCreate");日志输出. 先要引用 import android.uti ...

  10. js实现对json数据的序列化(兼容ie6以上浏览器)

    /** * 增加对JSON数据的序列化方法, * 主要用于IE6.7不支持JSON对象的浏览器 */ var xue = xue || {};xue.json = xue.json || {}; xu ...