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.

255 lines
7.4 KiB

  1. local EapSocket = EapClass("EapSocket")
  2. local scheduler = import(".scheduler")
  3. local wsClinet = import("..EapFunc.websocket.websocket")
  4. local proto = import(".proto")
  5. local bit = require("luaScript.ModuleEapSdk.EapFunc.websocket.bit")
  6. local SOCKET_NUM_COUNT = 1
  7. function EapSocket:ctor()
  8. self._mbSocket = nil
  9. self._listener = {}
  10. self._adapter = {}
  11. self._sendData = {}
  12. self._address = nil
  13. self._connected = false
  14. self._schedulerID = -1 -- 发消息线程
  15. self._recvSchID = -1 -- 收消息线程
  16. self._closeBack = nil --断线回调
  17. self:initData()
  18. end
  19. function EapSocket:initData()
  20. end
  21. -- 心跳时间
  22. local KEEP_ALIVE_TIMEOUT = 30
  23. function EapSocket:isConnected()
  24. return self._connected
  25. end
  26. -- 地址,端口,链接成功回调,链接失败回调,收到消息回调
  27. function EapSocket:connect(address, closeBack, connectBack)
  28. if (self._connected) then
  29. if (connectBack) then
  30. connectBack(true)
  31. end
  32. return true
  33. end
  34. if (not address) then
  35. return false
  36. end
  37. self._mbSocket = wsClinet.new(address)
  38. EapDump(self._mbSocket, "EapSocket ==== ")
  39. if not self._mbSocket then
  40. print("创建连接失败" .. address)
  41. return false
  42. end
  43. if (self._mbSocket.status >= 2 and self._mbSocket.status <= 3) then
  44. if (self._mbSocket) then
  45. self._mbSocket.close()
  46. self._mbSocket = nil
  47. end
  48. if (connectBack) then
  49. connectBack(false)
  50. return false
  51. end
  52. return false
  53. end
  54. self._address = address
  55. self._closeBack = closeBack
  56. self._connectBack = connectBack
  57. self._mbSocket.onopen = function()
  58. print("EapSocket OnOpen")
  59. if (self._connectBack) then
  60. local callback = self._connectBack
  61. self._connectBack = nil
  62. callback(true);
  63. end
  64. end
  65. self._mbSocket.onmessage = function(_, strData)
  66. print("EapSocket OnMessage:", strData)
  67. if type(strData) == "table" then
  68. strData = string.char(unpack(strData))
  69. end
  70. local opcode, data = self:parsePacket(strData)
  71. -- local data = G_EapSdkJson.decode(strData)
  72. self:onReceivedData(opcode, data)
  73. end
  74. --区分是否当前创建的socket
  75. local curSocketNum = SOCKET_NUM_COUNT + 1
  76. SOCKET_NUM_COUNT = SOCKET_NUM_COUNT + 1
  77. self._mbSocket.socketNum = curSocketNum
  78. self._mbSocket.onclose = function(_, code, reason)
  79. print("EapSocket OnClose", self._mbSocket.socketNum, curSocketNum)
  80. self._connected = false;
  81. if (self._mbSocket and self._mbSocket.socketNum == curSocketNum) then
  82. print("EapSocket OnClose 11111111111111")
  83. self:onclose()
  84. end
  85. end
  86. self._mbSocket.onerror = function(_, err)
  87. print("EapSocket OnError", self._mbSocket.socketNum, curSocketNum, err)
  88. if (self._mbSocket and self._mbSocket.socketNum == curSocketNum) then
  89. print("EapSocket OnError 11111111111111")
  90. self:onclose()
  91. end
  92. end
  93. self._recvSchID = scheduler.scheduleGlobal(function()
  94. self._mbSocket:update()
  95. end, 0.05)
  96. self._connected = true
  97. self._schedulerID = scheduler.scheduleGlobal(handler(self, self.peakPacket), 0.05)
  98. return true
  99. end
  100. --重新连接
  101. function EapSocket:reConnect()
  102. return self:connect(self._address, self._onClose)
  103. end
  104. -- 关闭连接
  105. function EapSocket:close()
  106. self:onclose()
  107. end
  108. function EapSocket:onclose()
  109. print("EapSocket:onclose ============ ")
  110. self._connected = false
  111. self._sendData = {}
  112. if (self._mbSocket) then
  113. scheduler.unscheduleGlobal(self._schedulerID)
  114. scheduler.unscheduleGlobal(self._recvSchID)
  115. local nullFun = function() end
  116. self._mbSocket.onopen = nullFun
  117. self._mbSocket.onmessage = nullFun
  118. self._mbSocket.onclose = nullFun
  119. self._mbSocket.onerror = nullFun
  120. self._mbSocket:close();
  121. self._mbSocket = nil;
  122. end
  123. if (self._connectBack) then
  124. local callback = self._connectBack
  125. self._connectBack = nil;
  126. callback(false);
  127. elseif (self._closeBack) then
  128. local callback = self._closeBack
  129. self._closeBack = nil;
  130. callback(false);
  131. end
  132. end
  133. -- 这里是提供给LUA逻辑层的网络协议发送接口
  134. function EapSocket:sendPacket(opcode, data, format, sendFormat )
  135. if (self._mbSocket) then
  136. if (self._mbSocket.state == "OPEN") then
  137. local buffer = self:serializePacket(opcode, data, format, sendFormat)
  138. self._sendData[#self._sendData+1] = buffer
  139. return
  140. end
  141. else
  142. print("连接断开,不重新连接服务器")
  143. if (self._serType == SER_TYPE_LOGIN) then
  144. local buffer = self:serializePacket(opcode, data, format, sendFormat)
  145. self._sendData[#self._sendData+1] = buffer
  146. self:reConnect()
  147. end
  148. return
  149. end
  150. if (self._mbSocket) then
  151. print("发送消息", data)
  152. local buffer = self:serializePacket(opcode, data, format, sendFormat)
  153. self._sendData[#self._sendData+1] = buffer
  154. end
  155. end
  156. function EapSocket:peakPacket()
  157. if (self._mbSocket and #self._sendData>0) then
  158. print("EapSocket:peakPacket = ", self._sendData[1])
  159. self._mbSocket:send(self._sendData[1])
  160. table.remove(self._sendData, 1)
  161. end
  162. end
  163. function EapSocket:onReceivedData(opcode, data)
  164. assert(false, "EapSocket:onReceivedData 此方法需要被继承")
  165. end
  166. -- | compress | 1 | 0:未压缩, 1:压缩,只针对data字段压缩 |
  167. -- | format | 7 | 0:自定义, 1:protobuf, 2:json,3:xml |
  168. -- | 扩展字段 | 8 | 自定义数据格式,原样返回, app用来定义消息id用的,自增,app可以用来区分是哪条消息的返回数据
  169. -- | opcode | 16 | 网络协议的类型标识,根据该标识进行反序列化 |
  170. -- | len | 16 | 网络包的长度,其值为除len字段外的其它所有长度 |
  171. -- len可以没有,如果compress==0;没有len;compress==1;才有len字段
  172. function EapSocket:serializePacket(opcode, data, format, sendFormat)
  173. sendFormat = sendFormat or 0
  174. format = format or 1 --返回数据格式,处理带float类型的json
  175. if data and opcode and G_EapProtos[opcode] then
  176. print("发送数据:", opcode)
  177. EapDump(data)
  178. local len = 0
  179. local buffer = data
  180. if sendFormat == 0 then
  181. buffer = proto.serialize(data, G_EapProtos[opcode])
  182. end
  183. len = len + string.len(buffer)
  184. local opcodeStr = proto.int16ToBufStr(opcode)
  185. local op1 = bit.lshift(sendFormat, 4) + format
  186. local op1Str = string.char(op1)
  187. local op2 = 0
  188. local op2Str = string.char(op2)
  189. len = len + 4
  190. if op1 == 1 or op1 == 2 or op1 == 33 or op1 == 34 then
  191. buffer = op1Str..op2Str..opcodeStr..buffer
  192. elseif op1 == 129 or op1 == 130 then
  193. local op3 = len
  194. local op3Str = string.char(op3)
  195. buffer = op1Str..op2Str..opcodeStr..op3Str..buffer
  196. end
  197. return buffer
  198. end
  199. end
  200. function EapSocket:parsePacket(buffer)
  201. local tbl = nil
  202. local opcode = nil
  203. local op1 = string.byte(buffer, 1, 1)
  204. local compress = bit.rshift(op1, 7)
  205. local type = bit.band(op1, 0x7f) --format格式
  206. local dataIndex = 5
  207. if compress == 1 then
  208. dataIndex = 7
  209. end
  210. local op2, op3 = string.byte(buffer, 3, 4)
  211. opcode = proto.buffToInt16(op2, op3)
  212. print("MBSocket:parsePacket Opcode == ", opcode, compress, type, string.len(buffer))
  213. if type == 1 or type == 0 or op1 == 33 or op1 == 34 then --proto
  214. if G_EapProtos[opcode] then
  215. local leftBuff = string.sub(buffer, dataIndex)
  216. tbl = proto.parse(leftBuff, G_EapProtos[opcode])
  217. EapDump(tbl, "protobuffer")
  218. return opcode, tbl
  219. else
  220. print("no such protos!!")
  221. end
  222. elseif type == 2 or type == 35 then --json
  223. local leftBuff = string.sub(buffer, dataIndex)
  224. tbl = G_EapSdkJson.decode(leftBuff) or {}
  225. tbl.nRet = tbl.nRet or tbl.CRet or 0
  226. EapDump(tbl, "json")
  227. return opcode, tbl
  228. end
  229. end
  230. return EapSocket