using System; using System.Collections.Generic; using Ice; using System.Web.Helpers; using CommonLang; using System.Collections.Concurrent; using Pomelo.JSGModule; using BattleIce; namespace Pomelo { public class IceLogger : Ice.Logger { private log4net.ILog logger; public IceLogger() { this.logger = log4net.LogManager.GetLogger("Ice"); } public Logger cloneWithPrefix(string prefix) { throw new NotImplementedException(); } public void error(string message) { this.logger.Error(message); } public string getPrefix() { throw new NotImplementedException(); } public void print(string message) { this.logger.Info(message); } public void trace(string category, string message) { //this.logger.Debug(message); } public void warning(string message) { this.logger.Warn(message); } } public class IceConfig { /// /// 启动host /// public string host = "127.0.0.1"; /// /// 启动端口 /// public int port; /// /// 是否输出连接警告 /// public bool isWarnConnections = true; /// /// 是否输出网络日志 /// public bool isTraceNetwork = false; /// /// 是否输出协议日志 /// public bool isTraceProtocol = false; } /** ice通知消息信息 */ public class ICENotifyData { public string name; public string jsonData; // 通知数据 public long failTime; // 失败时间 public ICENotifyData(string name, string jsonData) { this.name = name; this.jsonData = jsonData; this.failTime = CommonLang.TimeUtil.GetTimestampMS(); } } public class ICEZoneSession { private CommonLang.Log.Logger log = CommonLang.Log.LoggerFactory.GetLogger("ICEZoneSession"); public string srvUUID; public ZoneManagerCallbackPrx client; public ZoneManagerCallbackPrx callback; public IFastSession fastSession; public int failTimes = 0; public ConcurrentQueue notifyFailData = new ConcurrentQueue(); public ICEZoneSession(string srvUUID, ZoneManagerCallbackPrx client, ZoneManagerCallbackPrx callback) { try { this.srvUUID = srvUUID; this.client = client; this.callback = callback; this.failTimes = 0; } catch(System.Exception e) { log.Error("ICEZoneSession create catch :" + e); } } public bool setFastSession(IFastSession session) { this.fastSession = session; this.failTimes = 0; return true; } /** 重新通知所有时间 */ public void RetryFailNotifys() { try { this.callback.ice_ping(); } catch (System.Exception e) { log.Warn("RetryFailNotifys ping 异常:", e); } try { log.Info("RetryFailNotifys start begin 1: " + notifyFailData.Count); this.callback.ice_ping(); long ltimeEnd = CommonLang.TimeUtil.GetTimestampMS() - 120000; while (notifyFailData.Count > 0) { ICENotifyData notifyData = new ICENotifyData("", ""); if (notifyFailData.TryDequeue(out notifyData) && ltimeEnd < notifyData.failTime) { log.Info("RetryFailNotifys start begin 2: " + notifyFailData.Count + ", " + notifyData.name + ", " + notifyData.jsonData + ", time: " + notifyData.failTime); this.callback.eventNotify(notifyData.name, notifyData.jsonData); } else { log.Info("RetryFailNotifys start begin 3 skip: " + notifyFailData.Count + ", " + notifyData.name + ", " + notifyData.jsonData + ", time: " + notifyData.failTime); } } } catch(System.Exception e) { log.Error("RetryFailNotifys catch: " + e.Message, e); } } } public class IceManager : Ice.Application { private static IceManager _instance; private CommonLang.Log.Logger log = CommonLang.Log.LoggerFactory.GetLogger("IceManager"); private Dictionary proxys; /// /// 战斗服到游戏服ICE通知 /// private HashMap callbacks = new HashMap(); public ICEZoneSession getCallback(string gameServerId) { lock (callbacks) { return callbacks.Get(gameServerId); } } public int setCallback(string gameServerId, string srvUUID, ZoneManagerCallbackPrx client, ZoneManagerCallbackPrx callback) { lock (callbacks) { ICEZoneSession cacheSession = callbacks.Get(gameServerId); if (cacheSession != null && cacheSession.callback != null) { try { cacheSession.callback.ice_ping(); log.Error("已有服务器在线ice, 拒绝连接!"); return GSBindResult.ALREADY_EXISTS; } catch(System.Exception) { try { log.Error("ice连入,远端已经失效,重新设置!"); cacheSession.callback = callback; bool reconnect = cacheSession.srvUUID.Equals(srvUUID); //重连处理失败的逻辑 if (reconnect) { cacheSession.RetryFailNotifys(); } cacheSession.srvUUID = srvUUID; return reconnect ? GSBindResult.JOIN_RECONNECT : GSBindResult.JOIN_OK; } catch (System.Exception e) { log.Error("setCallback未处理异常:", e); return GSBindResult.UNKOWN; } } } else { callbacks.Put(gameServerId, new ICEZoneSession(srvUUID, client, callback)); } } return GSBindResult.JOIN_OK; } public bool setFastSession(string gameServerId, IFastSession session) { lock (callbacks) { ICEZoneSession cacheSession = callbacks.Get(gameServerId); if (cacheSession != null) { if(cacheSession.fastSession != null && cacheSession.fastSession.IsConnected()) { ///sesion.fastSession.doClose(); log.Error("已有服务器在线socket:" + gameServerId + ", " + cacheSession.fastSession.GetDescribe() + ", " + session.GetDescribe()); return false; } return cacheSession.setFastSession(session); } else { log.Error("setFastSession 找不到ice信息:" + gameServerId + ", " + session.ConnectorId + ", " + session.GetDescribe()); return false; } } } //private ZoneManagerCallbackPrx callback; //public ZoneManagerCallbackPrx Callback //{ // get { return callback; } // set { callback = value; } //} /// /// 单件实例 /// /// public static IceManager instance() { if (_instance == null) { _instance = new IceManager(); } return _instance; } public override int run(string[] args) { if (args.Length > 0) { log.Error(appName() + ": too many arguments"); return 1; } Ice.ObjectAdapter adapter = communicator().createObjectAdapter("CSharp"); foreach (var e in proxys) { log.Warn($"add ice adapter: {e.Key}"); adapter.add(e.Value, communicator().stringToIdentity(e.Key)); } adapter.activate(); log.Info("ICE started !"); communicator().waitForShutdown(); return 0; } public int Start(IceConfig config, Dictionary proxys) { this.proxys = proxys; Ice.InitializationData initData = new Ice.InitializationData(); //设置日志 initData.logger = new IceLogger(); initData.logger.print(Json.Encode(config)); //设置参数 initData.properties = Ice.Util.createProperties(); initData.properties.setProperty("CSharp.Endpoints", "tcp -p " + config.port); initData.properties.setProperty("Ice.Default.Host", config.host); initData.properties.setProperty("Ice.Warn.Connections", config.isWarnConnections ? "1" : "0"); initData.properties.setProperty("Ice.ACM.Close", "0"); //Ice.ACM.Timeout没有,相当于无用设置 initData.properties.setProperty("Ice.ACM.Heartbeat", "3"); initData.properties.setProperty("Ice.ThreadPool.Server.Size", "4"); initData.properties.setProperty("Ice.ThreadPool.Server.SizeMax", "8"); initData.properties.setProperty("Ice.MessageSizeMax", "10240"); initData.properties.setProperty("Ice.RetryIntervals", "0 500 2000 5000"); initData.properties.setProperty("Ice.Trace.Network", config.isTraceNetwork ? "1" : "0"); initData.properties.setProperty("Ice.Trace.Protocol", config.isTraceProtocol ? "1" : "0"); initData.properties.setProperty("Ice.Trace.Retry", "2"); var thread = new System.Threading.Thread(() => { log.Warn("ICE starting at " + config.host + ":" + config.port); this.main(new string[0], initData); }); thread.Name = "ICE run"; thread.Start(); return 0; } public void Stop() { communicator().shutdown(); communicator().destroy(); } //public void eventNotify(string eventType, string msg) //{ // if (callback != null) // { // callback.eventNotify(eventType, msg); // } //} //private IceManager(IceConfig config, Dictionary proxys) //{ // this.config = config; // this.proxys = proxys; //} private IceManager() { } } }