You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
10 KiB

  1. NetBase = class("NetBase");
  2. NetClientState =
  3. {
  4. Disconnect = 0,
  5. Connectting = 1,
  6. Connected = 2,
  7. }
  8. local function gettable(tab , key , defaultValue)
  9. local value = tab[key];
  10. if value then
  11. return value
  12. else
  13. value = defaultValue
  14. tab[key] = value
  15. return value
  16. end
  17. end
  18. local function NetworkFuncGet(self , moduleID)
  19. return gettable(self, moduleID, {
  20. get = function(self , cmdID)
  21. return gettable(self, cmdID, {
  22. funcs = {},
  23. callbacks = {},
  24. dirty = true,
  25. insert = function(self , func)
  26. self.funcs[func] = 1
  27. self.dirty = true
  28. end,
  29. remove = function(self , func)
  30. self.funcs[func] = nil
  31. self.dirty = true
  32. end,
  33. })
  34. end,
  35. })
  36. end
  37. -- 构造函数
  38. function NetBase:ctor()
  39. -- 保存(模块->命令->函数)的对应关系
  40. self.mNetworkFunc = {}
  41. -- 保存(函数->模块、命令)的对应关系
  42. self.mFuncToCmd = {}
  43. self.mNetworkFunc.get = NetworkFuncGet
  44. -- 初始状态下是不需要重连的
  45. -- 第一次成功链接后才设置为需要重连
  46. -- 再往后可以根据需要修改
  47. self.isNeedReconnect = false
  48. -- 游戏切换到后台之后缓存的服务器消息,
  49. -- 切换回来之后手动发送一遍
  50. self.isBackGround = false;
  51. self.netMessageStack = {}
  52. app:addEventListener("applicationDidEnterBackground", handler(self,self.onApplicationDidEnterBackground))
  53. app:addEventListener("applicationWillEnterForeground", handler(self, self.onApplicationWillEnterForeground))
  54. end
  55. -- 需重写:连接时的回调
  56. function NetBase:OnConnecttingCallback()
  57. end
  58. -- 需重写:连接成功之后的回调
  59. function NetBase:OnConnectedCallback()
  60. end
  61. -- 需重写:断开连接时的回调
  62. function NetBase:OnDisconnectCallback()
  63. end
  64. -- 是否处于链接状态
  65. function NetBase:isConnected()
  66. if self.Socket then
  67. return self.Socket:state() == NetClientState.Connected;
  68. else
  69. return false
  70. end
  71. end
  72. --
  73. function NetBase:isInited()
  74. return self.Socket ~= nil;
  75. end
  76. function NetBase:onRecvServerMsg(moduleID , cmdID , statusCode , stream)
  77. end
  78. --------------------------------------------------------------------------------------
  79. --------------------------------------------------------------------------------------
  80. --------------------------------------------------------------------------------------
  81. --------------------------------------------------------------------------------------
  82. -- 注册一个网络消息回调
  83. function NetBase:regMsg(moduleID , cmdID , func)
  84. if type(func) ~= "function" then
  85. error("regMsg时传入了不正确的function,moduleID[" .. tostring(moduleID) .. "] cmdID[" .. tostring(cmdID) .. "] func[" .. tostring(func) .. "]");
  86. return
  87. end
  88. self.mNetworkFunc:get(moduleID):get(cmdID):insert(func);
  89. self.mFuncToCmd[func] = {moduleID,cmdID};
  90. end
  91. -- 反注册一个网络消息
  92. function NetBase:unregMsg(func)
  93. if type(func) ~= "function" then
  94. error("unregMsg时传进来的第一个参数不是function");
  95. end
  96. local funcToCmd = self.mFuncToCmd[func];
  97. if funcToCmd == nil then
  98. return
  99. end
  100. self.mNetworkFunc:get(funcToCmd[1]):get(funcToCmd[2]):remove(func);
  101. self.mFuncToCmd[func] = nil;
  102. end
  103. -- 通过命令ID移除网络消息监听
  104. function NetBase:removeMsgHandler(cmdID)
  105. for func,funcToCmd in pairs(self.mFuncToCmd) do
  106. if funcToCmd[2]==cmdID then
  107. self:unregMsg(func)
  108. end
  109. end
  110. end
  111. -- 发送消息到服务器
  112. function NetBase:send(moduleID , cmdID , stream)
  113. print(string.format("发送消息:moduleID[%d] cmdID[%#x] size[%d]", moduleID, cmdID, NetStream.getWriteSize(stream)));
  114. -- 如果网络已经断开,则果断提示错误
  115. if self.Socket:state() ~= NetClientState.Connected then
  116. --NetStream.delete(stream)
  117. showTooltip("网络已断开");
  118. return;
  119. end
  120. self.Socket:send(moduleID , cmdID , stream)
  121. end
  122. -- 发送一个命令(不带用户数据)到服务器
  123. function NetBase:sendCmd(moduleID , cmdID)
  124. local stream = NetStream.new();
  125. self:send(moduleID , cmdID , stream);
  126. NetStream.delete(stream)
  127. end
  128. -- 网络消息处理函数
  129. function NetBase:onNetworkMsg(moduleID , cmdID , statusCode , stream)
  130. if statusCode ~= 0 then
  131. --showTooltip("statusCode = "..statusCode);
  132. print(string.format("接受消息:moduleID[%d] cmdID[%#x] statusCode[%d]", moduleID, cmdID, statusCode));
  133. else
  134. print(string.format("接受消息:moduleID[%d] cmdID[%#x] statusCode[%d] size[%d]", moduleID, cmdID, statusCode, NetStream.getReadSize(stream)));
  135. end
  136. local mod = self.mNetworkFunc[moduleID];
  137. if mod then
  138. local cmd = mod[cmdID];
  139. if cmd then
  140. if cmd.dirty then
  141. cmd.dirty = false
  142. cmd.callbacks = {}
  143. for i,v in pairs(cmd.funcs) do
  144. cmd.callbacks[i] = v
  145. end
  146. end
  147. local funcs = cmd.callbacks
  148. for func,v in pairs(funcs) do
  149. NetStream.reset(stream);
  150. func(statusCode , stream);
  151. end
  152. if cmd.dirty then
  153. cmd.callbacks = {}
  154. end
  155. end
  156. end
  157. end
  158. -- 开始连接
  159. function NetBase:connect(ip, port)
  160. log("moduleID[99] - NetBase:connect() ")
  161. if self.Socket and self.Socket:state() == NetClientState.Connectting then
  162. --showTooltip("moduleID[99] - is Connectting, return")
  163. return;
  164. end
  165. -- 处理 socket 状态变化
  166. local function onState(state)
  167. log("NetBase::connect() onState() state = ", tostring(state))
  168. if state == NetClientState.Connectting then
  169. log("moduleID[99] - Connectting")
  170. self:OnConnecttingCallback()
  171. elseif state == NetClientState.Connected then
  172. log("moduleID[99] - Connected")
  173. -- self:closeTimer();
  174. app.waitDialogManager:closeWaitNetworkDialog()
  175. self:OnConnectedCallback()
  176. elseif state == NetClientState.Disconnect then
  177. log("moduleID[99] - Disconnect")
  178. -- self:closeTimer();
  179. app.waitDialogManager:closeWaitNetworkDialog()
  180. self:OnDisconnectCallback()
  181. end
  182. end
  183. -- 处理服务器消息
  184. local function onMessage(moduleID , cmdID , statusCode , stream)
  185. -- 如果游戏退入后台,则拦截所有除心跳之外的消息
  186. -- 回来的时候再轮流处理
  187. if self.isPause and cmdID ~= 0x2008 then
  188. local streamData = NetStream.getReadData(stream);
  189. local newStream = NetStream.new(streamData);
  190. table.insert(self.netMessageStack, {moduleID=moduleID, cmdID=cmdID , statusCode=statusCode , stream=newStream})
  191. else
  192. self:onNetworkMsg(moduleID , cmdID , statusCode , stream)
  193. self:onRecvServerMsg(moduleID , cmdID , statusCode , stream)
  194. end
  195. end
  196. if not self.Socket then
  197. self.Socket = NetClient.new(onMessage , onState);
  198. -- 网宿水印
  199. local setting = require("luaScript.Config.Setting")
  200. if setting and setting.NetClientParams then
  201. local v = setting.NetClientParams
  202. local num = #setting.NetClientParams
  203. if num == 5 then
  204. self.Socket:setParams(v[1], v[2], v[3], v[4], v[5])
  205. end
  206. end
  207. local timeOut = 5;
  208. if isIOSReviewVersion() then
  209. timeOut = 30;
  210. end
  211. if self.Socket.setConnectTimeout then
  212. self.Socket:setConnectTimeout(timeOut)
  213. end
  214. if self.Socket.setWriteTimeout then
  215. self.Socket:setWriteTimeout(timeOut)
  216. end
  217. if self.Socket.setReadTimeout then
  218. self.Socket:setReadTimeout(timeOut)
  219. end
  220. end
  221. -- 记录当前使用的ip和端口
  222. self.ip = ip;
  223. self.port = port;
  224. if not ip or not port then
  225. showTooltip("无效的 ip 或 port");
  226. return;
  227. end
  228. -- 连接网络
  229. app.waitDialogManager:showWaitNetworkDialog("登录中....")
  230. -- self:startTimer();
  231. if isDebug() then
  232. showTooltip("尝试链接 "..ip.." : "..port)
  233. end
  234. log("尝试链接 "..ip.." : "..port)
  235. self.netMessageStack = {}
  236. getHostAndIpByUrl(ip, function(host2, ip2)
  237. if ip2 then
  238. self.Socket:connect(ip2, port)
  239. else
  240. self.Socket:connect(ip, port)
  241. end
  242. end)
  243. end
  244. -- 断开连接
  245. function NetBase:close()
  246. log("200000 moduleID[99] NetBase:close()")
  247. if self.Socket then
  248. self.Socket:close();
  249. end
  250. end
  251. -- 开始连接后启动计时器,指定的时间没有连接上,记为超时
  252. function NetBase:startTimer()
  253. log("moduleID[99] NetBase:startTimer()");
  254. local function outTimeCallback()
  255. log("moduleID[99] NetBase:startTimer() outTimeCallback()");
  256. self:close()
  257. end
  258. -- 先关闭,再创建
  259. self:closeTimer()
  260. local timeOut = getNetTimeOutNum();
  261. log("moduleID[99] NetBase:startTimer() timeOut = ", tostring(timeOut));
  262. self.scheduleHandle = cc.Director:getInstance():getScheduler():scheduleScriptFunc(outTimeCallback, timeOut, false);
  263. log("moduleID[99] NetBase:startTimer() scheduleHandle = ", tostring(self.scheduleHandle));
  264. end
  265. function NetBase:closeTimer()
  266. log("moduleID[99] NetBase:closeTimer()");
  267. if self.scheduleHandle then
  268. log("moduleID[99] NetBase:closeTimer() unscheduleScriptEntry ", tostring(self.scheduleHandle));
  269. cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.scheduleHandle);
  270. self.scheduleHandle = nil;
  271. else
  272. log("moduleID[99] NetBase:closeTimer() scheduleHandle is nil");
  273. end
  274. end
  275. function NetBase:onApplicationDidEnterBackground()
  276. self:onMsgPause()
  277. end
  278. function NetBase:onApplicationWillEnterForeground()
  279. self:onMsgResume();
  280. end
  281. function NetBase:onMsgPause()
  282. log("moduleID[99] NetBase:onMsgPause")
  283. self.isPause = true
  284. end
  285. function NetBase:onMsgResume()
  286. log("moduleID[99] NetBase:onMsgResume")
  287. if self.netMessageStack and #self.netMessageStack > 0 then
  288. app:dispatchEvent({name = "onDealMessageStackBegin" , net = self});
  289. for k,v in ipairs(self.netMessageStack) do
  290. self:onNetworkMsg(v.moduleID , v.cmdID, v.statusCode , v.stream)
  291. self:onRecvServerMsg(v.moduleID , v.cmdID, v.statusCode , v.stream)
  292. NetStream.delete(v.stream);
  293. end
  294. app:dispatchEvent({name = "onDealMessageStackEnd" , net = self});
  295. end
  296. self:onMsgClear();
  297. self.isPause = false
  298. end
  299. function NetBase:onMsgResumeEx()
  300. self.isPause=false
  301. while #self.netMessageStack > 0 do
  302. if self.isPause then
  303. return
  304. end
  305. self:runNextMsg()
  306. end
  307. end
  308. function NetBase:runNextMsg()
  309. log("NetBase:runNextMsg")
  310. if self.netMessageStack and #self.netMessageStack > 0 then
  311. local v = self.netMessageStack[1]
  312. table.remove(self.netMessageStack,1)
  313. self:onNetworkMsg(v.moduleID , v.cmdID, v.statusCode , v.stream)
  314. self:onRecvServerMsg(v.moduleID , v.cmdID, v.statusCode , v.stream)
  315. NetStream.delete(v.stream)
  316. return true
  317. end
  318. return false
  319. end
  320. function NetBase:onMsgClear()
  321. self.netMessageStack = {}
  322. end
  323. return NetBase;