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
}
///
/// 建议使用方法:
/// 做为客户端,都使用 FObjSys.Current 连接不同的服务器
/// 做为服务器,当要提供2个Obj服务, 应该要使用 Currents[index]
/// 这套逻辑已经潜入到 每个 FObj 中, FObj.CurrObjSys, 就是对应的 Obj服务
///
public class FObjSys : IFObjSysAsClient, IFObjSysAsServer
{
///
/// nlog调试信息
///
static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
///
/// 全局 当前正在操作的 fobj系统
///
public static FObjSys Current;
///
/// fobj系统数组
///
public static List Currents = new List();
///
/// 作为服务器 监听客户端到本地的连接请求
///
TCPListen m_tcplisten;
///
/// 作为客户端 管理连接到异地服务器的连接
///
Dictionary> m_cconns = new Dictionary>();
///
/// 作为服务器,当异地客户端断开,发送通知
///
List m_serverConnectedNotifyObjID = new List();
///
/// 交易列表
///
List Transactions = new List();
///
/// 消息推送的敏感对象
///
class Sense
{
public IFConn conn;
public UInt32 objid;
public UInt32 sense_mask;
}
///
/// 加入到 fobj系统的 obj
///
Dictionary> Objs = new Dictionary>();
static FObjSys()
{
Currents.Add(new FObjBase.FObjSys());
Current = Currents[0];
}
public FObjSys() {
}
#region IFObjSys
///
/// 添加OBJ到系统
///
///
public void ObjAdd(IFObj obj)
{
if (obj.ID == 0)
obj.ID = GetFreeObjID();
Objs.Add(obj, new List());
}
///
/// 对外发送消息
///
/// 远端对应的连接代理
/// 远端的ID
/// 本地的ID
/// 交易码
/// 信息码
/// 信息内容
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 服务端
///
/// 启动本地OBJSys网络
///
///
///
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;
}
///
/// 指定推送到某个远端
///
///
///
///
///
///
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);
}
///
/// 推送到远端,系统判定根据敏感对象推送
///
///
///
///
public void PushObjInfoEx(IFObj srcobj, UInt16 infoid, byte[] infodata)
{
if (!Objs.Keys.Contains(srcobj))
return;
List 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);
}
}
///
/// 推送到远端,系统判定根据敏感对象推送,但不推送给特定某对象
///
///
///
///
///
///
public void PushObjInfoEx_except(IFObj srcobj, UInt16 infoid, byte[] infodata, IFConn except_s1, UInt32 except_destid)
{
if (!Objs.Keys.Contains(srcobj))
return;
List 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);
}
}
///
/// 回复 客户端的CallFunction
///
/// 客户端对应的连接代理
/// 客户端的对象ID
/// 本地服务端的对象ID
/// 交易码
/// 函数ID
/// 函数返回
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 客户端
///
/// 获取没用使用的OBJID
///
///
public UInt32 GetFreeObjID()
{
if (Objs.Count > 0)
return Objs.Max(obj => obj.Key.ID) + 1;
else
return 1;
}
///
/// 从系统删除OBJ
///
///
public void ObjRemove(IFObj obj)
{
Objs.Remove(obj);//作为服务端,关闭推送服务
foreach (var kv in m_cconns)
{
kv.Value.Remove(obj.ID);
}
}
///
/// 作为客户端,从系统删除OBJ;
/// 还会通知服务器,断开与这个 OBJ 的所有连接
///
///
///
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);
}
}
///
/// 连接到远端的OBJSys连接
///
/// 远端地址
/// 连接成功后,通知这些obj
///
public TCPCConn Connect_to_Another_OBJSys(IPEndPoint ep, params UInt32[] objids)
{
try
{
KeyValuePair> 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(objids));
return conn;
}
}
///
/// 断开到远端OBJSys的连接
///
/// 远端地址
/// 连接成功后,通知这些obj
///
public void Disconnect_to_Another_OBJSys(IPEndPoint ep, params UInt32[] objids)
{
try
{
KeyValuePair> 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
{
}
}
///
/// 注册本地obj 为远端obj的敏感对象,得到远端obj的推送消息
///
/// 远端对应的连接代理
/// 远端的ID
/// 本地obj
/// 注册的敏感源
/// 动作,添加?删除?
public void SenseConfigEx(IFConn s1, UInt32 objid, UInt32 senobjid, UInt32 sense_mask, SENSE_CONFIG action)
{
if (s1 == null)
return;
List buf = new List();
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());
}
///
/// 向远端GetValue
///
/// 远端对应的连接代理
/// 远端的ID
/// 本地的ID
/// 成员ID
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);
}
///
/// 向远端SetValue
///
/// 远端对应的连接代理
/// 远端的ID
/// 本地的ID
/// 成员ID
/// 成员内容
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);
}
///
/// 向远端CallFunction
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
/// 函数ID
/// 函数参数
/// 在其上调用异步调用的委托对象
/// 作为 BeginInvoke 方法调用的最后一个参数而提供的对象
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;
}
///
/// 向远端CallFunction
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
/// 函数ID
/// 函数参数
public UInt32 CallFunctionEx(IFConn s1, UInt32 destid, UInt32 srcid, UInt16 funcid, byte[] param)
{
return CallFunctionEx(s1, destid, srcid, funcid, param, null, null);
}
///
/// 发送大包数据
///
///
///
///
///
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());
}
///
/// 客户端接收大包数据
///
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;
}
}
}
///
/// 服务器接收大包数据
///
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
///
/// 通过objid 查找 obj
///
///
///
IFObj Find(UInt32 objid)
{
try
{
KeyValuePair> obj_kv = Objs.First(obj => obj.Key.ID == objid);
return obj_kv.Key;
}
catch
{
return null;
}
}
UInt32 free_magic = 1;
///
/// 获取一个没有被分配的 交易码
///
///
UInt32 GetFreeMagic()
{
UInt32 f = free_magic;
free_magic++;
if (free_magic == 0)
free_magic++;
//if (free_magic > UInt32.MaxValue)
// freetranno = 1;
return f;
}
///
/// 作为客户端,与服务器连续状态改变
///
///
void CConnConnectAction(IFConn conn)
{
TCPCConn cc = (TCPCConn)conn;
if (logger.IsDebugEnabled)
{
logger.Debug($"(C) CConnConnectAction {cc.RemoteEP} conn.IsConnected={conn.IsConnected}");
}
KeyValuePair> 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;
}
}
///
/// 作为服务器端,客户的登陆与退出
///
///
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 senses = Objs.ElementAt(i).Value;
senses.RemoveAll(s => s.conn == conn);
}
//删除所有与它有关的 tran
Transactions.RemoveAll(t => t.Conn == conn);
}
}
///
/// 作为服务器端,客户端 的 某obj 注销了,把它相关的都删除
///
///
///
void ClearRemoteObjConn(IFConn conn, UInt32 srcid)
{
//删除推送
for (int i = 0; i < Objs.Keys.Count(); i++)
{
List 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的函数指针
///
/// 本地,给Protocol的函数指针;
/// GetValue
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
///
///
///
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);
}
///
/// 本地,给Protocol的函数指针;
/// SetValue
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
///
///
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);
}
///
/// 本地,给Protocol的函数指针;
/// CallFunction
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
/// 交易号
/// 功能号
/// 参数
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);
}
///
/// 本地,给Protocol的函数指针;
/// Sense_Config
///
/// 远端对应的连接代理
/// 远端对象ID
/// 本地对象ID
/// 远端对象 关注 本地对象 的敏感源
/// 动作,添加?删除?
void Sense_Config(IFConn from, UInt32 srcid, UInt32 destid, UInt32 sense_mask, SENSE_CONFIG action)
{
try
{
KeyValuePair> 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
///
/// 从异端接收的数据,解释数据
///
///
///
///
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;
}
///
/// 从异端接收的数据,解释数据
///
///
///
///
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;
}
}
}