using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.ComponentModel; namespace FObjBase { public enum SENSE_CONFIG { ADD, REMOVE } /// <summary> /// 建议使用方法: /// 做为客户端,都使用 FObjSys.Current 连接不同的服务器 /// 做为服务器,当要提供2个Obj服务, 应该要使用 Currents[index] /// 这套逻辑已经潜入到 每个 FObj 中, FObj.CurrObjSys, 就是对应的 Obj服务 /// </summary> public class FObjSys : IFObjSysAsClient, IFObjSysAsServer { /// <summary> /// nlog调试信息 /// </summary> static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// <summary> /// 全局 当前正在操作的 fobj系统 /// </summary> public static FObjSys Current; /// <summary> /// fobj系统数组 /// </summary> public static List<FObjSys> Currents = new List<FObjSys>(); /// <summary> /// 作为服务器 监听客户端到本地的连接请求 /// </summary> TCPListen m_tcplisten; /// <summary> /// 作为客户端 管理连接到异地服务器的连接 /// </summary> Dictionary<TCPCConn, List<UInt32>> m_cconns = new Dictionary<TCPCConn, List<UInt32>>(); /// <summary> /// 作为服务器,当异地客户端断开,发送通知 /// </summary> List<UInt32> m_serverConnectedNotifyObjID = new List<UInt32>(); /// <summary> /// 交易列表 /// </summary> List<Transaction> Transactions = new List<Transaction>(); /// <summary> /// 消息推送的敏感对象 /// </summary> class Sense { public IFConn conn; public UInt32 objid; public UInt32 sense_mask; } /// <summary> /// 加入到 fobj系统的 obj /// </summary> Dictionary<IFObj, List<Sense>> Objs = new Dictionary<IFObj, List<Sense>>(); static FObjSys() { Currents.Add(new FObjBase.FObjSys()); Current = Currents[0]; } public FObjSys() { } #region IFObjSys /// <summary> /// 添加OBJ到系统 /// </summary> /// <param name="obj"></param> public void ObjAdd(IFObj obj) { if (obj.ID == 0) obj.ID = GetFreeObjID(); Objs.Add(obj, new List<Sense>()); } /// <summary> /// 对外发送消息 /// </summary> /// <param name="s1">远端对应的连接代理 </param> /// <param name="destid">远端的ID</param> /// <param name="srcid">本地的ID</param> /// <param name="magic">交易码</param> /// <param name="info_no">信息码</param> /// <param name="info_data">信息内容</param> public void SendMessageEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt32 magic, UInt16 info_no, byte[] info_data) { if (s1 == null) return; if (s1 is FConnLocal) { return; } else { var p = new Pack_Proto() { destid = destid, srcid = srcid, magic = magic, info = info_no, buf = info_data }; ((TCPConn)s1).SendPacket(p.ToBytes()); if (!(s1 is TCPCConn)) { if (logger.IsDebugEnabled) { logger.Debug($"(S) SendMessageEx{Environment.NewLine}{Pack_ProtoToString(p)}"); } } return; } } static string BytesToHexString(byte[] buf) { int row = 0; StringBuilder sb = new StringBuilder(); StringBuilder sb_hex = new StringBuilder(); StringBuilder sb_str = new StringBuilder(); sb.Append($" | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | "); sb.AppendLine(); sb.Append($"--------| -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |----------------"); sb.AppendLine(); for (int i = 0; i < buf.Count(); i++) { sb_hex.Append($"{buf[i]:X2} "); char c = (char)buf[i]; if (c > 0x20 && c < 0x7e) { sb_str.Append(c); } else { sb_str.Append(" "); } if ((i + 1) % 16 == 0) { sb.Append($"{row * 16:X08}| {sb_hex}|{sb_str}"); row++; sb.AppendLine(); sb_hex.Clear(); sb_str.Clear(); } } int remaining = buf.Count() % 16; if (remaining > 0) { for (int i = 0; i < (16 - remaining); i++) { sb_hex.Append(" "); sb_str.Append(" "); } sb.Append($"{row * 16:X08}| {sb_hex}|{sb_str}"); row++; sb.AppendLine(); sb_hex.Clear(); sb_str.Clear(); } return sb.ToString(); } static string Pack_ProtoToString(Pack_Proto p) { StringBuilder sb = new StringBuilder(); sb.AppendLine($"destid=0x{p.destid:x8}, srcid=0x{p.srcid:x8}, magic={p.magic}, info=0x{p.info:x4}, buf="); sb.Append(BytesToHexString(p.buf)); return sb.ToString(); } #region 服务端 /// <summary> /// 启动本地OBJSys网络 /// </summary> /// <param name="ep"></param> /// <param name="objids"></param> public void Start_Conn_Server(IPEndPoint ep, params UInt32[] objids) { m_serverConnectedNotifyObjID.AddRange(objids); if (m_tcplisten == null) { m_tcplisten = new TCPListen(ep) { ParsePacket = new ParsePacketHandler(ParsePacketInServer), ConnectAction = new ConnectHandler(SConnConnectAction), }; } else { m_tcplisten.Enable = false; m_tcplisten.LocalEP = ep; } m_tcplisten.Enable = true; } /// <summary> /// 指定推送到某个远端 /// </summary> /// <param name="srcobj"></param> /// <param name="infoid"></param> /// <param name="infodata"></param> /// <param name="s1"></param> /// <param name="destid"></param> public void PushObjInfoEx(IFObj srcobj, UInt16 infoid, byte[] infodata, IFConn s1, UInt32 destid) { if (s1 is FConnLocal) { IFObj obj = Find(destid); if (obj != null) obj.PushInfo(s1, srcobj.ID, infoid, infodata); return; } PushAny(s1, destid, srcobj.ID, GetFreeMagic(), Proto.INFO_PUSH_EVENT, infoid, infodata); } /// <summary> /// 推送到远端,系统判定根据敏感对象推送 /// </summary> /// <param name="srcobj"></param> /// <param name="infoid"></param> /// <param name="infodata"></param> public void PushObjInfoEx(IFObj srcobj, UInt16 infoid, byte[] infodata) { if (!Objs.Keys.Contains(srcobj)) return; List<Sense> senses = Objs[srcobj]; //foreach (Sense sense in senses) // sense.hasPush = false; int cnt = senses.Count(); for (int i = 0; i < cnt; i++) { Sense sense = senses[i]; if ((sense.sense_mask & (1 << infoid)) == 0) continue; if (sense.conn is FConnLocal) { IFObj obj = Find(sense.objid); if (obj != null) obj.PushInfo(sense.conn, srcobj.ID, infoid, infodata); continue; } PushAny(sense.conn, sense.objid, srcobj.ID, GetFreeMagic(), Proto.INFO_PUSH_EVENT, infoid, infodata); } } /// <summary> /// 推送到远端,系统判定根据敏感对象推送,但不推送给特定某对象 /// </summary> /// <param name="srcobj"></param> /// <param name="infoid"></param> /// <param name="infodata"></param> /// <param name="except_s1"></param> /// <param name="except_destid"></param> public void PushObjInfoEx_except(IFObj srcobj, UInt16 infoid, byte[] infodata, IFConn except_s1, UInt32 except_destid) { if (!Objs.Keys.Contains(srcobj)) return; List<Sense> senses = Objs[srcobj]; //foreach (Sense sense in senses) // sense.hasPush = false; int cnt = senses.Count(); for (int i = 0; i < cnt; i++) { Sense sense = senses[i]; if ((sense.sense_mask & (1 << infoid)) == 0) continue; if ((sense.conn == except_s1) && (sense.objid == except_destid)) continue; if (sense.conn is FConnLocal) { IFObj obj = Find(sense.objid); if (obj != null) obj.PushInfo(sense.conn, srcobj.ID, infoid, infodata); continue; } PushAny(sense.conn, sense.objid, srcobj.ID, GetFreeMagic(), Proto.INFO_PUSH_EVENT, infoid, infodata); } } /// <summary> /// 回复 客户端的CallFunction /// </summary> /// <param name="s1">客户端对应的连接代理 </param> /// <param name="destid">客户端的对象ID</param> /// <param name="srcid">本地服务端的对象ID</param> /// <param name="magic">交易码</param> /// <param name="funcid">函数ID</param> /// <param name="retdata">函数返回</param> public void PushCallFunctionEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt32 magic, UInt16 funcid, byte[] retdata) { if (s1 == null) return; if (s1 is FConnLocal) { var ts = from t in Transactions where t.Magic == magic && t.Conn == s1 select t; if (ts.Count() > 0) { Transaction tran = ts.First(); Transactions.Remove(tran); PushCallFunction(s1, srcid, destid, magic, funcid, retdata, tran.AsyncDelegate, tran.AsyncContext); } else { PushCallFunction(s1, srcid, destid, magic, funcid, retdata, null, null); } return; } PushAny(s1, destid, srcid, magic, Proto.INFO_PUSH_CALL_FUNCTION, funcid, retdata); } void PushAny(IFConn s1, UInt32 destid, UInt32 srcid, UInt32 magic, UInt16 infoid, UInt16 funcid, byte[] retdata) { PushAny(s1, destid, srcid, magic, infoid, funcid, retdata, null, null); } void PushAny(IFConn s1, UInt32 destid, UInt32 srcid, UInt32 magic, UInt16 infoid, UInt16 funcid, byte[] retdata, AsyncCBHandler asyncDelegate, object asyncContext) { if ((retdata != null) && (retdata.Length > Transaction.PackSize)) //参数太大,需要分包多次发送 { //安全检测 if (Transactions.Any(tran => tran.Magic == magic && tran.Conn == s1)) { //不应该有 throw new Exception($"推送大包出错,在 交易队列已经 magic={magic}"); } Transaction t = new Transaction() { Conn = s1, SrcObjID = destid, Magic = magic, Size = retdata.Length, Buf = (byte[])retdata.Clone(), InfoId = infoid, FuncID = funcid, AsyncDelegate = asyncDelegate, AsyncContext = asyncContext }; Transactions.Add(t); SendBigSize(s1, destid, srcid, magic); } else { if (asyncDelegate != null) { Transaction t = new Transaction() { Conn = s1, SrcObjID = destid, Magic = magic, InfoId = infoid, FuncID = funcid, AsyncDelegate = asyncDelegate, AsyncContext = asyncContext }; Transactions.Add(t); } Pack_GetSetPushCall p = new Pack_GetSetPushCall { infoid = funcid, infodata = retdata }; SendMessageEx(s1, destid, srcid, magic, infoid, p.ToBytes()); } } #endregion #region 客户端 /// <summary> /// 获取没用使用的OBJID /// </summary> /// <returns></returns> public UInt32 GetFreeObjID() { if (Objs.Count > 0) return Objs.Max(obj => obj.Key.ID) + 1; else return 1; } /// <summary> /// 从系统删除OBJ /// </summary> /// <param name="obj"></param> public void ObjRemove(IFObj obj) { Objs.Remove(obj);//作为服务端,关闭推送服务 foreach (var kv in m_cconns) { kv.Value.Remove(obj.ID); } } /// <summary> /// 作为客户端,从系统删除OBJ; /// 还会通知服务器,断开与这个 OBJ 的所有连接 /// </summary> /// <param name="obj"></param> /// <param name="conn"></param> public void ObjRemove(IFObj obj, IFConn conn) { ObjRemove(obj); Transactions.RemoveAll(t => t.SrcObjID == obj.ID); if (conn != null) { SendMessageEx(conn, 0, obj.ID, GetFreeMagic(), Proto.INFO_OBJ_DISPOSE, null); } } /// <summary> /// 连接到远端的OBJSys连接 /// </summary> /// <param name="ep">远端地址</param> /// <param name="objids">连接成功后,通知这些obj</param> /// <returns></returns> public TCPCConn Connect_to_Another_OBJSys(IPEndPoint ep, params UInt32[] objids) { try { KeyValuePair<TCPCConn, List<UInt32>> cc_kv; cc_kv = m_cconns.First(_cc => _cc.Key.RemoteEP.Equals(ep)); cc_kv.Value.AddRange(objids); //已经存在此连接,通知 if (cc_kv.Key.IsConnected) { foreach (UInt32 objid in objids) { IFObj obj = Find(objid); if (obj != null) obj.ConnectNotify(cc_kv.Key); } } return cc_kv.Key; } catch { TCPCConn conn = new TCPCConn(ep) { ParsePacket = new ParsePacketHandler(ParsePacketInClient), ConnectAction = new ConnectHandler(CConnConnectAction), Enable = true }; m_cconns.Add(conn, new List<uint>(objids)); return conn; } } /// <summary> /// 断开到远端OBJSys的连接 /// </summary> /// <param name="ep">远端地址</param> /// <param name="objids">连接成功后,通知这些obj</param> /// <returns></returns> public void Disconnect_to_Another_OBJSys(IPEndPoint ep, params UInt32[] objids) { try { KeyValuePair<TCPCConn, List<UInt32>> cc_kv; cc_kv = m_cconns.First(_cc => _cc.Key.RemoteEP.Equals(ep)); cc_kv.Value.RemoveAll(objid => objids.Contains(objid)); //删除大通讯的trans Transactions.RemoveAll(t => objids.Contains(t.SrcObjID)); if (cc_kv.Key.IsConnected)//它的连接是正常的,通知objids,说连接断开了 { foreach (UInt32 objid in objids) { IFObj obj = Find(objid); if (obj != null) obj.ConnectNotify( new TCPCConn(ep) { Enable = false }); } } if (cc_kv.Value.Count == 0)//已经没有obj需要连接了,删除conn { cc_kv.Key.Enable = false; m_cconns.Remove(cc_kv.Key); } } catch { } } /// <summary> /// 注册本地obj 为远端obj的敏感对象,得到远端obj的推送消息 /// </summary> /// <param name="s1">远端对应的连接代理 </param> /// <param name="objid">远端的ID</param> /// <param name="senobjid">本地obj</param> /// <param name="sense_mask">注册的敏感源</param> /// <param name="action">动作,添加?删除?</param> public void SenseConfigEx(IFConn s1, UInt32 objid, UInt32 senobjid, UInt32 sense_mask, SENSE_CONFIG action) { if (s1 == null) return; List<byte> buf = new List<byte>(); if (action == SENSE_CONFIG.ADD) buf.Add(0); else buf.Add(1); buf.AddRange(BitConverter.GetBytes(sense_mask)); SendMessageEx(s1, objid, senobjid, GetFreeMagic(), Proto.INFO_CONFIG_SENSE_OBJ, buf.ToArray()); } /// <summary> /// 向远端GetValue /// </summary> /// <param name="s1">远端对应的连接代理</param> /// <param name="destid">远端的ID</param> /// <param name="srcid">本地的ID</param> /// <param name="memid">成员ID</param> public void GetValueEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt16 memid) { if (s1 == null) return; if (s1 is FConnLocal) { byte[] value; GetValue(s1, srcid, destid, memid, out value); if (value != null) PushGetValue(s1, destid, srcid, memid, value); return; } PushAny(s1, destid, srcid, GetFreeMagic(), Proto.INFO_GET_VALUE, memid, null); } /// <summary> /// 向远端SetValue /// </summary> /// <param name="s1">远端对应的连接代理</param> /// <param name="destid">远端的ID</param> /// <param name="srcid">本地的ID</param> /// <param name="memid">成员ID</param> /// <param name="value">成员内容</param> public void SetValueEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt16 memid, byte[] value) { if (s1 == null) return; if (s1 is FConnLocal) { SetValue(s1, srcid, destid, memid, value); return; } PushAny(s1, destid, srcid, GetFreeMagic(), Proto.INFO_SET_VALUE, memid, value); } /// <summary> /// 向远端CallFunction /// </summary> /// <param name="s1">远端对应的连接代理 </param> /// <param name="destid">远端对象ID</param> /// <param name="srcid">本地对象ID</param> /// <param name="funcid">函数ID</param> /// <param name="param">函数参数</param> /// <param name="asyncDelegate">在其上调用异步调用的委托对象</param> /// <param name="asyncContext">作为 BeginInvoke 方法调用的最后一个参数而提供的对象</param> public UInt32 CallFunctionEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt16 funcid, byte[] param, AsyncCBHandler asyncDelegate, object asyncContext) { if (s1 == null) return 0; UInt32 magic = GetFreeMagic(); if (s1 is FConnLocal) { if ((asyncDelegate != null) || (asyncContext != null)) //需要返回参数!!! { Transaction t = new Transaction() { Conn = s1, SrcObjID = destid, Magic = magic, AsyncDelegate = asyncDelegate, AsyncContext = asyncContext }; Transactions.Add(t); } CallFunction(s1, srcid, destid, magic, funcid, param); return magic; } PushAny(s1, destid, srcid, magic, Proto.INFO_CALL_FUNCTION, funcid, param, asyncDelegate, asyncContext); return magic; } /// <summary> /// 向远端CallFunction /// </summary> /// <param name="s1">远端对应的连接代理 </param> /// <param name="destid">远端对象ID</param> /// <param name="srcid">本地对象ID</param> /// <param name="funcid">函数ID</param> /// <param name="param">函数参数</param> public UInt32 CallFunctionEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt16 funcid, byte[] param) { return CallFunctionEx(s1, destid, srcid, funcid, param, null, null); } /// <summary> /// 发送大包数据 /// </summary> /// <param name="conn"></param> /// <param name="destid"></param> /// <param name="srcid"></param> /// <param name="magic"></param> void SendBigSize( IFConn conn, UInt32 destid, UInt32 srcid, UInt32 magic) { var ts = from t in Transactions where t.Magic == magic && t.Conn == conn select t; if (ts.Count() == 0) return; Transaction tran = ts.First(); if (tran.GetBigSize(out Pack_BigSize pack)) { //缓冲区的数据都发送完了!!!!! if (tran.Reset())//复位缓冲区 { //不需要回调,直接删除 交易 Transactions.Remove(tran); } //需要回调的交易留着,通过magic匹配 } SendMessageEx(conn, destid, srcid, magic, Proto.INFO_PUSH_BIGSIZE, pack.ToBytes()); } /// <summary> /// 客户端接收大包数据 /// </summary> void ReciveBigSizeInClient(IFConn conn, Pack_Proto p) { Pack_BigSize pack = new Pack_BigSize(); if (!pack.TryParse(p.buf)) throw new Exception("解析大包出错"); //找到交易, 没有就创建 var ts = from t in Transactions where t.Conn == conn && t.Magic == p.magic select t; Transaction tran; if (ts.Count() == 0) { tran = new Transaction() { Conn = conn, SrcObjID = p.destid, Magic = p.magic }; Transactions.Add(tran); } else { if (ts.Count() > 1) { throw new Exception("接收大包时,出错,交易列表中 有2条或以上的交易号一样"); } tran = ts.First(); } if (!tran.ToBuf(pack))//把大包放入 交易的缓冲 { //还没获取完大包,继续问服务器获取 if (tran.InfoId == Proto.INFO_PUSH_CALL_FUNCTION) { //如果是callfunction, 引发进度事件 PushCallFunctionBigSizeStatus(conn, p.srcid, p.destid, p.magic, tran.FuncID, tran.Size, tran.Position, tran.AsyncContext); } //继续获取参数!!!!!!!!! SendMessageEx(conn, p.srcid, p.destid, p.magic, Proto.INFO_REQUEST_BIGSIZE, null); } else { //大包接收完了 //交易完成,删除 Transactions.Remove(tran); if (tran.InfoId == Proto.INFO_PUSH_CALL_FUNCTION) { //如果是callfunction, 引发进度事件 PushCallFunctionBigSizeStatus(conn, p.srcid, p.destid, p.magic, tran.FuncID, tran.Size, tran.Position, tran.AsyncContext); } switch (tran.InfoId) { case Proto.INFO_PUSH_CALL_FUNCTION: PushCallFunction(conn, p.srcid, p.destid, p.magic, tran.FuncID, tran.Buf, tran.AsyncDelegate, tran.AsyncContext); break; case Proto.INFO_PUSH_GET_VALUE: PushGetValue(conn, p.srcid, p.destid, tran.FuncID, tran.Buf); break; case Proto.INFO_PUSH_EVENT: PushObjInfo(conn, p.srcid, p.destid, tran.FuncID, tran.Buf); break; } } } /// <summary> /// 服务器接收大包数据 /// </summary> void ReciveBigSizeInServer(IFConn conn, Pack_Proto p) { Pack_BigSize pack = new Pack_BigSize(); if (!pack.TryParse(p.buf)) throw new Exception("解析大包出错"); //找到交易, 没有就创建 var ts = from t in Transactions where t.Conn == conn && t.Magic == p.magic select t; Transaction tran; if (ts.Count() == 0) { tran = new Transaction() { Conn = conn, SrcObjID = p.destid, Magic = p.magic }; Transactions.Add(tran); } else { if (ts.Count() > 1) { throw new Exception("接收大包时,出错,交易列表中 有2条或以上的交易号一样"); } tran = ts.First(); } if (!tran.ToBuf(pack))//把大包放入 交易的缓冲 { //继续获取参数!!!!!!!!! SendMessageEx(conn, p.srcid, p.destid, p.magic, Proto.INFO_REQUEST_BIGSIZE, null); } else { //大包接收完了 Transactions.Remove(tran);//用完了,删除!!! switch (tran.InfoId) { case Proto.INFO_CALL_FUNCTION: CallFunction(conn, p.srcid, p.destid, p.magic, tran.FuncID, tran.Buf); break; case Proto.INFO_SET_VALUE: SetValue(conn, p.srcid, p.destid, tran.FuncID, tran.Buf); break; } } } #endregion #endregion /// <summary> /// 通过objid 查找 obj /// </summary> /// <param name="objid"></param> /// <returns></returns> IFObj Find(UInt32 objid) { try { KeyValuePair<IFObj, List<Sense>> obj_kv = Objs.First(obj => obj.Key.ID == objid); return obj_kv.Key; } catch { return null; } } UInt32 free_magic = 1; /// <summary> /// 获取一个没有被分配的 交易码 /// </summary> /// <returns></returns> UInt32 GetFreeMagic() { UInt32 f = free_magic; free_magic++; if (free_magic == 0) free_magic++; //if (free_magic > UInt32.MaxValue) // freetranno = 1; return f; } /// <summary> /// 作为客户端,与服务器连续状态改变 /// </summary> /// <param name="conn"></param> void CConnConnectAction(IFConn conn) { TCPCConn cc = (TCPCConn)conn; if (logger.IsDebugEnabled) { logger.Debug($"(C) CConnConnectAction {cc.RemoteEP} conn.IsConnected={conn.IsConnected}"); } KeyValuePair<TCPCConn, List<UInt32>> cc_kv; try { cc_kv = m_cconns.First(_cc => _cc.Key == cc); foreach (UInt32 objid in cc_kv.Value) { IFObj obj = Find(objid); if (obj != null) obj.ConnectNotify(cc); } } catch(Exception e) { throw e; } } /// <summary> /// 作为服务器端,客户的登陆与退出 /// </summary> /// <param name="conn"></param> void SConnConnectAction(IFConn conn) { if (logger.IsDebugEnabled) { if (conn is TCPConn) { logger.Debug($"(S) SConnConnectAction IsConnected={conn.IsConnected}"); } } //通知obj 连接状态 foreach (UInt32 objid in m_serverConnectedNotifyObjID) { IFObj obj = Find(objid); if (obj != null) obj.ConnectNotify(conn); } //当通讯断开时,还要把关注的推送删除掉 if(conn.IsConnected==false) { for (int i = 0; i < Objs.Keys.Count(); i++) { List<Sense> senses = Objs.ElementAt(i).Value; senses.RemoveAll(s => s.conn == conn); } //删除所有与它有关的 tran Transactions.RemoveAll(t => t.Conn == conn); } } /// <summary> /// 作为服务器端,客户端 的 某obj 注销了,把它相关的都删除 /// </summary> /// <param name="conn"></param> /// <param name="srcid"></param> void ClearRemoteObjConn(IFConn conn, UInt32 srcid) { //删除推送 for (int i = 0; i < Objs.Keys.Count(); i++) { List<Sense> senses = Objs.ElementAt(i).Value; senses.RemoveAll(s => (s.conn == conn) && (s.objid == srcid)); } //删除所有与它有关的 tran Transactions.RemoveAll(t => t.Conn == conn && t.SrcObjID == srcid); } #region 本地,给Protocol的函数指针 /// <summary> /// 本地,给Protocol的函数指针; /// GetValue /// </summary> /// <param name="from">远端对应的连接代理</param> /// <param name="srcid">远端对象ID</param> /// <param name="destid">本地对象ID</param> /// <param name="memid"></param> /// <param name="value"></param> /// <returns></returns> void GetValue(IFConn from,UInt32 srcid,UInt32 destid, UInt16 memid,out byte[] value) { value = null; IFObj destobj = Find(destid); if (destobj == null) return; destobj.GetValue(from, srcid,memid,out value); } /// <summary> /// 本地,给Protocol的函数指针; /// SetValue /// </summary> /// <param name="from">远端对应的连接代理</param> /// <param name="srcid">远端对象ID</param> /// <param name="destid">本地对象ID</param> /// <param name="memid"></param> /// <param name="value"></param> void SetValue(IFConn from, UInt32 srcid, UInt32 destid, UInt16 memid, byte[] value) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.SetValue(from, srcid, memid, value); } /// <summary> /// 本地,给Protocol的函数指针; /// CallFunction /// </summary> /// <param name="from">远端对应的连接代理</param> /// <param name="srcid">远端对象ID</param> /// <param name="destid">本地对象ID</param> /// <param name="magic">交易号</param> /// <param name="funcid">功能号</param> /// <param name="param">参数</param> void CallFunction(IFConn from, UInt32 srcid, UInt32 destid, UInt32 magic, UInt16 funcid, byte[] param) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.CallFunction(from, srcid, magic, funcid, param); } /// <summary> /// 本地,给Protocol的函数指针; /// Sense_Config /// </summary> /// <param name="from">远端对应的连接代理</param> /// <param name="srcid">远端对象ID</param> /// <param name="destid">本地对象ID</param> /// <param name="sense_mask">远端对象 关注 本地对象 的敏感源</param> /// <param name="action">动作,添加?删除?</param> void Sense_Config(IFConn from, UInt32 srcid, UInt32 destid, UInt32 sense_mask, SENSE_CONFIG action) { try { KeyValuePair<IFObj, List<Sense>> obj_kv = Objs.First(obj => obj.Key.ID == destid); Sense sense = obj_kv.Value.Find(s=>s.conn == from && s.objid==srcid); if (sense == null) { if (action == SENSE_CONFIG.ADD) { Sense s = new Sense() { conn = from, objid = srcid, sense_mask = sense_mask }; obj_kv.Value.Add(s); } } else { if (action == SENSE_CONFIG.ADD) { sense.sense_mask |= sense_mask; } else { sense.sense_mask &= ~sense_mask; } } } catch { //不能找到对应的objid } } void PushObjInfo(IFConn from, UInt32 srcid, UInt32 destid, UInt16 infoid, byte[] infodata) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.PushInfo(from, srcid, infoid, infodata); } void PushGetValue(IFConn from, UInt32 srcid, UInt32 destid, UInt16 infoid, byte[] infodata) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.PushGetValue(from, srcid, infoid, infodata); } void PushCallFunction(IFConn from, UInt32 srcid, UInt32 destid, UInt32 magic, UInt16 infoid, byte[] infodata, AsyncCBHandler asyncDelegate, object asyncContext) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.PushCallFunction(from, srcid, magic, infoid, infodata, asyncDelegate, asyncContext); } void PushCallFunctionBigSizeStatus(IFConn from, UInt32 srcid, UInt32 destid, UInt32 magic, UInt16 infoid, int total_size, int download_size, object asyncContext) { IFObj destobj = Find(destid); if (destobj == null) return; destobj.PushCallFunctionBigSizeStatus(from, srcid, magic, infoid, total_size, download_size, asyncContext); } int Process(IFConn from, UInt32 srcid, UInt32 destid, UInt32 magic, UInt16 info_no, byte[] infodata, out byte[] retdata) { retdata = null; IFObj destobj = Find(destid); if (destobj == null) return -1; return destobj.ProcessEx(from, srcid, magic, info_no, infodata,out retdata); } #endregion /// <summary> /// 从异端接收的数据,解释数据 /// </summary> /// <param name="packet"></param> /// <param name="conn"></param> /// <returns></returns> bool ParsePacketInClient(byte[] packet, IFConn conn) { Pack_Proto p = new Pack_Proto(); if (!p.TryParse(packet)) return false; if (logger.IsDebugEnabled) { logger.Debug($"(C) ParsePacketInClient {Environment.NewLine}{Pack_ProtoToString(p)}"); } conn.TranID = p.magic; { if (Process(conn, p.srcid, p.destid, p.magic, p.info, p.buf, out byte[] retdata) == 0) { if (retdata != null) { SendMessageEx(conn, p.srcid, p.destid, p.magic, p.info, retdata); } return true; } } switch (p.info) { case Proto.INFO_PUSH_EVENT: { Pack_GetSetPushCall pack = new Pack_GetSetPushCall(); if (!pack.TryParse(p.buf)) return false; PushObjInfo(conn, p.srcid, p.destid, pack.infoid, pack.infodata); }break; case Proto.INFO_PUSH_GET_VALUE: { Pack_GetSetPushCall pack = new Pack_GetSetPushCall(); if (!pack.TryParse(p.buf)) return false; PushGetValue(conn, p.srcid, p.destid, pack.infoid, pack.infodata); }break; case Proto.INFO_PUSH_CALL_FUNCTION: { Pack_GetSetPushCall pack = new Pack_GetSetPushCall(); if (!pack.TryParse(p.buf)) return false; var ts = from t in Transactions where (t.Magic == p.magic) && (t.Conn == conn) select t; if (ts.Count() > 0) { Transaction tran = ts.First(); Transactions.Remove(tran);//用完,删除 PushCallFunction(conn, p.srcid, p.destid, p.magic, pack.infoid, pack.infodata, tran.AsyncDelegate, tran.AsyncContext); } else { PushCallFunction(conn, p.srcid, p.destid, p.magic, pack.infoid, pack.infodata, null, null); } } break; case Proto.INFO_REQUEST_BIGSIZE: { SendBigSize(conn, p.srcid, p.destid, p.magic); } break; case Proto.INFO_PUSH_BIGSIZE: { ReciveBigSizeInClient(conn, p); } break; } return true; } /// <summary> /// 从异端接收的数据,解释数据 /// </summary> /// <param name="packet"></param> /// <param name="conn"></param> /// <returns></returns> bool ParsePacketInServer(byte[] packet, IFConn conn) { Pack_Proto p = new Pack_Proto(); if (!p.TryParse(packet)) return false; conn.TranID = p.magic; { if (Process(conn, p.srcid, p.destid, p.magic, p.info, p.buf, out byte[] retdata) == 0) { if (retdata != null) { SendMessageEx(conn, p.srcid, p.destid, p.magic, p.info, retdata); } return true; } } switch (p.info) { case Proto.INFO_SET_VALUE: { Pack_GetSetPushCall p_info = new Pack_GetSetPushCall(); if (!p_info.TryParse(p.buf)) throw new Exception("解析 SetValue 出错"); SetValue(conn, p.srcid, p.destid, p_info.infoid, p_info.infodata); } break; case Proto.INFO_GET_VALUE: { Pack_GetSetPushCall p_info = new Pack_GetSetPushCall(); if (!p_info.TryParse(p.buf)) throw new Exception("解析 GetValue 出错"); GetValue(conn, p.srcid, p.destid, p_info.infoid, out byte[] value); if (value != null) { PushAny(conn, p.srcid, p.destid, p.magic, Proto.INFO_PUSH_GET_VALUE, p_info.infoid, value); } } break; case Proto.INFO_CALL_FUNCTION: { Pack_GetSetPushCall p_info = new Pack_GetSetPushCall(); if (!p_info.TryParse(p.buf)) throw new Exception("解析 CallFunction 出错"); CallFunction(conn, p.srcid, p.destid, p.magic, p_info.infoid, p_info.infodata); } break; case Proto.INFO_CONFIG_SENSE_OBJ: { SENSE_CONFIG action; if (p.buf[0] == 0) action = SENSE_CONFIG.ADD; else action = SENSE_CONFIG.REMOVE; UInt32 mask = BitConverter.ToUInt32(p.buf, 1); Sense_Config(conn, p.srcid, p.destid, mask, action); } break; case Proto.INFO_OBJ_DISPOSE: { ClearRemoteObjConn(conn, p.srcid); } break; case Proto.INFO_PUSH_BIGSIZE: { //服务器端,收到客户端 的 大包 ReciveBigSizeInServer(conn, p); }break; case Proto.INFO_REQUEST_BIGSIZE: { //服务器端,收到客户端 “请继续发送回复大包” 请求 SendBigSize(conn, p.srcid, p.destid, p.magic); }break; } //DateTime dt1 = DateTime.Now; //Console.WriteLine("FObjSys ParsePacketInServer " + "p.info=" + p.info.ToString() + " " + (dt1 - dt2).TotalMilliseconds.ToString() + " " + (dt1 - dtlast).TotalMilliseconds.ToString()); //dtlast = dt1; return true; } } }