|
- local Net = class("Net");
-
- NetClientState =
- {
- Disconnect = 0,
- Connectting = 1,
- Connected = 2,
- }
-
- local function gettable(tab , key , defaultValue)
- local value = tab[key];
- if value then
- return value
- else
- value = defaultValue
- tab[key] = value
- return value
- end
- end
-
- local function NetworkFuncGet(self , moduleID)
- return gettable(self, moduleID, {
- get = function(self , cmdID)
- return gettable(self, cmdID, {
- funcs = {},
- callbacks = {},
- dirty = true,
- insert = function(self , func)
- self.funcs[func] = 1
- self.dirty = true
- end,
- remove = function(self , func)
- self.funcs[func] = nil
- self.dirty = true
- end,
- })
- end,
- })
- end
-
- -- 构造函数
- function Net:ctor()
- -- 保存模块->命令->函数的对应关系
- self.mNetworkFunc = {}
- -- 保存函数->模块命令的对应关系
- self.mFuncToCmd = {}
- self.mNetworkFunc.get = NetworkFuncGet
-
- self.logTag = ""
-
- -- 所有IP
- self.netConfigMap = {}
-
- -- 当前IP的索引
- self.ipIndex = nil;
-
- -- 当前IP使用的次数
- self.curReconnectTimes = 0;
-
- -- 每个IP最多重连3次
- self.maxReconnectTimes = 3;
-
- self.OnState = function(state)end;
-
- -- 网络消息处理函数
- local function onNetworkMsg(moduleID , cmdID , statusCode , stream)
- if statusCode ~= 0 then
- showTooltip("statusCode = "..statusCode);
- print(string.format("接受消息:moduleID[%d] cmdID[%#x] statusCode[%d]", moduleID, cmdID, statusCode));
- else
- print(string.format("接受消息:moduleID[%d] cmdID[%#x] statusCode[%d] size[%d]", moduleID, cmdID, statusCode, NetStream.getReadSize(stream)));
- end
-
- local mod = self.mNetworkFunc[moduleID];
- if mod then
- local cmd = mod[cmdID];
- if cmd then
- if cmd.dirty then
- cmd.dirty = false
- cmd.callbacks = {}
- for i,v in pairs(cmd.funcs) do
- cmd.callbacks[i] = v
- end
- end
- local funcs = cmd.callbacks
- for func,v in pairs(funcs) do
- NetStream.reset(stream);
- func(statusCode , stream);
- end
- if cmd.dirty then
- cmd.callbacks = {}
- end
- end
- end
- end
- self.OnMessage = onNetworkMsg
-
- self.OnConnect = function()
- log(self.logTag.."net::OnConnect()")
- self.curReconnectTimes = 0;
- app:dispatchEvent({name = "onConnect" , net = self});
- end
-
- self.OnConnectting = function()
- log(self.logTag.."net::OnConnectting()")
- app:dispatchEvent({name = "onConnectting" , net = self});
- end
-
- self.OnDisconnect = function()
- log(self.logTag.."net::OnDisconnect()")
- app:dispatchEvent({name = "onDisconnect" , net = self});
- end
- end
-
- -- 清空网络端口列表
- function Net:clearIpList()
- -- 所有IP
- self.netConfigMap = {}
-
- -- 当前IP的索引
- self.ipIndex = nil;
-
- -- 当前IP使用的次数
- self.curReconnectTimes = 0;
- end
-
- -- 添加网络端口列表
- function Net:addIp(ip, port)
- if not ip or not port then
- return
- end
- if not self.netConfigMap then
- self.netConfigMap = {}
- end
-
- table.insert(self.netConfigMap, {ip = ip, port = port})
- end
-
- function Net:removeIp(index)
- local nSize = #self.netConfigMap
- if tonumber(index) <= tonumber(nSize) then
- table.remove(self.netConfigMap, tonumber(index))
- end
-
- -- 可用的IP地址用完了,就重启游戏,重新拉取新配置
- if #self.netConfigMap <= 0 then
- cc.Application:getInstance():restart();
- return
- end
- end
- -- 从网络端口列表中获取一个可用的端口
- function Net:getIp()
- if not self.netConfigMap or #self.netConfigMap <= 0 then
- return nil
- end
-
- self.ipIndex = math.random(#self.netConfigMap)
- self.curReconnectTimes = 0;
-
- local value = self.netConfigMap[self.ipIndex]
- return value.ip, value.port;
- end
-
-
- -- 注册一个网络消息回调
- function Net:regMsg(moduleID , cmdID , func)
- if type(func) ~= "function" then
- error("regMsg时传入了不正确的function,moduleID[" .. tostring(moduleID) .. "] cmdID[" .. tostring(cmdID) .. "] func[" .. tostring(func) .. "]");
- return
- end
- self.mNetworkFunc:get(moduleID):get(cmdID):insert(func);
- self.mFuncToCmd[func] = {moduleID,cmdID};
- end
-
- -- 反注册一个网络消息
- function Net:unregMsg(func)
- if type(func) ~= "function" then
- error("unregMsg时传进来的第一个参数不是function");
- end
- local funcToCmd = self.mFuncToCmd[func];
- if funcToCmd == nil then
- return
- end
- self.mNetworkFunc:get(funcToCmd[1]):get(funcToCmd[2]):remove(func);
- self.mFuncToCmd[func] = nil;
- end
-
- -- 通过命令ID移除网络消息监听
- function Net:removeMsgHandler(cmdID)
- for func,funcToCmd in pairs(self.mFuncToCmd) do
- if funcToCmd[2]==cmdID then
- self:unregMsg(func)
- end
- end
- end
-
- -- 发送消息到服务器
- function Net:send(moduleID , cmdID , stream)
- print(string.format("发送消息:moduleID[%d] cmdID[%#x] size[%d]", moduleID, cmdID, NetStream.getWriteSize(stream)));
- -- 如果网络已经断开,则果断提示错误
- if self.Socket:state() ~= NetClientState.Connected then
- local function run()
- local stream = NetStream.new();
- self.OnMessage(moduleID , cmdID , -2 , stream);
- NetStream.delete(stream)
- end
- runInNextFrame(run);
- return;
- end
- self.Socket:send(moduleID , cmdID , stream)
- end
-
- -- 重新连接
- function Net:reconnect()
- self:close();
- self.OnConnectting()
-
- -- 从网络配置中随机连接
- local ip, port
-
- if not self.ipIndex then
- ip, port = self:getIp()
- end
-
- if self.curReconnectTimes < self.maxReconnectTimes then
- local value = self.netConfigMap[self.ipIndex]
- if value then
- ip, port = value.ip, value.port;
- end
- print(string.format("%s Net:reconnect() use old ,ip = %s, port = %s",self.logTag, ip, port))
- else
- -- 删除当前使用的ip
- self:removeIp(self.ipIndex)
-
-
- -- 重新获取新的ip
- ip, port = self:getIp()
- print(string.format("%s Net:reconnect() use new ,ip = %s, port = %s",self.logTag, ip, port))
- end
-
- if not ip or not port then
- showTooltip("无效的IP地址")
- return
- end
-
- self.curReconnectTimes = self.curReconnectTimes + 1
-
- print(string.format("%s Net:reconnect() netConfigMap = %s",self.logTag, table.tostring(self.netConfigMap)))
-
- print(string.format("%s Net:reconnect() ipIndex = %s",self.logTag, self.ipIndex))
- print(string.format("%s Net:reconnect() curReconnectTimes = %s, maxReconnectTimes = %s",self.logTag, self.curReconnectTimes, self.maxReconnectTimes))
-
- self.IP = ip
- self.Port = port
- print("尝试重连:" .. tostring(self.IP) .. ":" .. tostring(self.Port));
- self.Socket:connect(self.IP, self.Port)
- end
-
- -- 连接服务器
- function Net:connect()
- self:reconnect();
- end
-
- -- 关闭连接
- function Net:close()
- if self.Socket then
- self.Socket:close();
- end
- end
-
- -- 是否已经连接了
- function Net:isinit()
- return self ~= nil and self.IP ~= nil and self.Port ~= nil;
- end
-
- -- 是否处于链接状态
- function Net:isConnected()
- return self.Socket:state() == NetClientState.Connected;
- end
-
- -- 启动网络模块
- function Net:startNet()
- local function onState(state)
- if state == NetClientState.Disconnect then
- self.OnDisconnect()
- elseif state == NetClientState.Connected then
- --self.mNetworkFunc = {}
- --self.mFuncToCmd = {}
- --self.mNetworkFunc.get = NetworkFuncGet
- -- 这里触发一个socket级别的连接成功回调
- app:dispatchEvent({name = "socketConnectSucceed" , net = self});
- self.OnConnect()
- end
- self.OnState(state);
- end
- local function onMessage(moduleID , cmdID , statusCode , stream)
- -- 处理服务器消息
- app:dispatchEvent{name = "netProcessMessage", moduleID = moduleID, cmdID = cmdID, statusCode = statusCode}
- self.OnMessage(moduleID , cmdID , statusCode , stream)
- end
- if not self.Socket then
- self.Socket = NetClient.new(onMessage , onState);
- if self.Socket.setConnectTimeout and isIOSReviewVersion() then
- self.Socket:setConnectTimeout(30)
- end
- if self.Socket.setWriteTimeout and isIOSReviewVersion() then
- self.Socket:setWriteTimeout(30)
- end
- if self.Socket.setReadTimeout and isIOSReviewVersion() then
- self.Socket:setReadTimeout(30)
- end
- end
-
- -- 创建新的网络连接
- self:reconnect();
- end
-
- -- 发送一个命令(不带用户数据)到服务器
- function Net:sendCmd(moduleID , cmdID)
- local stream = NetStream.new();
- self:send(moduleID , cmdID , stream);
- NetStream.delete(stream)
- end
-
- return Net;
|