local EapSocket = EapClass("EapSocket") local scheduler = import(".scheduler") local wsClinet = import("..EapFunc.websocket.websocket") local proto = import(".proto") local bit = require("luaScript.ModuleEapSdk.EapFunc.websocket.bit") local SOCKET_NUM_COUNT = 1 function EapSocket:ctor() self._mbSocket = nil self._listener = {} self._adapter = {} self._sendData = {} self._address = nil self._connected = false self._schedulerID = -1 -- 发消息线程 self._recvSchID = -1 -- 收消息线程 self._closeBack = nil --断线回调 self:initData() end function EapSocket:initData() end -- 心跳时间 local KEEP_ALIVE_TIMEOUT = 30 function EapSocket:isConnected() return self._connected end -- 地址,端口,链接成功回调,链接失败回调,收到消息回调 function EapSocket:connect(address, closeBack, connectBack) if (self._connected) then if (connectBack) then connectBack(true) end return true end if (not address) then return false end self._mbSocket = wsClinet.new(address) EapDump(self._mbSocket, "EapSocket ==== ") if not self._mbSocket then print("创建连接失败" .. address) return false end if (self._mbSocket.status >= 2 and self._mbSocket.status <= 3) then if (self._mbSocket) then self._mbSocket.close() self._mbSocket = nil end if (connectBack) then connectBack(false) return false end return false end self._address = address self._closeBack = closeBack self._connectBack = connectBack self._mbSocket.onopen = function() print("EapSocket OnOpen") if (self._connectBack) then local callback = self._connectBack self._connectBack = nil callback(true); end end self._mbSocket.onmessage = function(_, strData) print("EapSocket OnMessage:", strData) if type(strData) == "table" then strData = string.char(unpack(strData)) end local opcode, data = self:parsePacket(strData) -- local data = G_EapSdkJson.decode(strData) self:onReceivedData(opcode, data) end --区分是否当前创建的socket local curSocketNum = SOCKET_NUM_COUNT + 1 SOCKET_NUM_COUNT = SOCKET_NUM_COUNT + 1 self._mbSocket.socketNum = curSocketNum self._mbSocket.onclose = function(_, code, reason) print("EapSocket OnClose", self._mbSocket.socketNum, curSocketNum) self._connected = false; if (self._mbSocket and self._mbSocket.socketNum == curSocketNum) then print("EapSocket OnClose 11111111111111") self:onclose() end end self._mbSocket.onerror = function(_, err) print("EapSocket OnError", self._mbSocket.socketNum, curSocketNum, err) if (self._mbSocket and self._mbSocket.socketNum == curSocketNum) then print("EapSocket OnError 11111111111111") self:onclose() end end self._recvSchID = scheduler.scheduleGlobal(function() self._mbSocket:update() end, 0.05) self._connected = true self._schedulerID = scheduler.scheduleGlobal(handler(self, self.peakPacket), 0.05) return true end --重新连接 function EapSocket:reConnect() return self:connect(self._address, self._onClose) end -- 关闭连接 function EapSocket:close() self:onclose() end function EapSocket:onclose() print("EapSocket:onclose ============ ") self._connected = false self._sendData = {} if (self._mbSocket) then scheduler.unscheduleGlobal(self._schedulerID) scheduler.unscheduleGlobal(self._recvSchID) local nullFun = function() end self._mbSocket.onopen = nullFun self._mbSocket.onmessage = nullFun self._mbSocket.onclose = nullFun self._mbSocket.onerror = nullFun self._mbSocket:close(); self._mbSocket = nil; end if (self._connectBack) then local callback = self._connectBack self._connectBack = nil; callback(false); elseif (self._closeBack) then local callback = self._closeBack self._closeBack = nil; callback(false); end end -- 这里是提供给LUA逻辑层的网络协议发送接口 function EapSocket:sendPacket(opcode, data, format, sendFormat ) if (self._mbSocket) then if (self._mbSocket.state == "OPEN") then local buffer = self:serializePacket(opcode, data, format, sendFormat) self._sendData[#self._sendData+1] = buffer return end else print("连接断开,不重新连接服务器") if (self._serType == SER_TYPE_LOGIN) then local buffer = self:serializePacket(opcode, data, format, sendFormat) self._sendData[#self._sendData+1] = buffer self:reConnect() end return end if (self._mbSocket) then print("发送消息", data) local buffer = self:serializePacket(opcode, data, format, sendFormat) self._sendData[#self._sendData+1] = buffer end end function EapSocket:peakPacket() if (self._mbSocket and #self._sendData>0) then print("EapSocket:peakPacket = ", self._sendData[1]) self._mbSocket:send(self._sendData[1]) table.remove(self._sendData, 1) end end function EapSocket:onReceivedData(opcode, data) assert(false, "EapSocket:onReceivedData 此方法需要被继承") end -- | compress | 1 | 0:未压缩, 1:压缩,只针对data字段压缩 | -- | format | 7 | 0:自定义, 1:protobuf, 2:json,3:xml | -- | 扩展字段 | 8 | 自定义数据格式,原样返回, app用来定义消息id用的,自增,app可以用来区分是哪条消息的返回数据 -- | opcode | 16 | 网络协议的类型标识,根据该标识进行反序列化 | -- | len | 16 | 网络包的长度,其值为除len字段外的其它所有长度 | -- len可以没有,如果compress==0;没有len;compress==1;才有len字段 function EapSocket:serializePacket(opcode, data, format, sendFormat) sendFormat = sendFormat or 0 format = format or 1 --返回数据格式,处理带float类型的json if data and opcode and G_EapProtos[opcode] then print("发送数据:", opcode) EapDump(data) local len = 0 local buffer = data if sendFormat == 0 then buffer = proto.serialize(data, G_EapProtos[opcode]) end len = len + string.len(buffer) local opcodeStr = proto.int16ToBufStr(opcode) local op1 = bit.lshift(sendFormat, 4) + format local op1Str = string.char(op1) local op2 = 0 local op2Str = string.char(op2) len = len + 4 if op1 == 1 or op1 == 2 or op1 == 33 or op1 == 34 then buffer = op1Str..op2Str..opcodeStr..buffer elseif op1 == 129 or op1 == 130 then local op3 = len local op3Str = string.char(op3) buffer = op1Str..op2Str..opcodeStr..op3Str..buffer end return buffer end end function EapSocket:parsePacket(buffer) local tbl = nil local opcode = nil local op1 = string.byte(buffer, 1, 1) local compress = bit.rshift(op1, 7) local type = bit.band(op1, 0x7f) --format格式 local dataIndex = 5 if compress == 1 then dataIndex = 7 end local op2, op3 = string.byte(buffer, 3, 4) opcode = proto.buffToInt16(op2, op3) print("MBSocket:parsePacket Opcode == ", opcode, compress, type, string.len(buffer)) if type == 1 or type == 0 or op1 == 33 or op1 == 34 then --proto if G_EapProtos[opcode] then local leftBuff = string.sub(buffer, dataIndex) tbl = proto.parse(leftBuff, G_EapProtos[opcode]) EapDump(tbl, "protobuffer") return opcode, tbl else print("no such protos!!") end elseif type == 2 or type == 35 then --json local leftBuff = string.sub(buffer, dataIndex) tbl = G_EapSdkJson.decode(leftBuff) or {} tbl.nRet = tbl.nRet or tbl.CRet or 0 EapDump(tbl, "json") return opcode, tbl end end return EapSocket