c#网络通信框架networkcomms内核解析之九 自定义处理方法的运行机制
本文基于networkcomms2.3.1开源版本 gplv3协议
我们自己写的处理方法都称之为自定义处理方法
比如,我们在服务器上写的与登陆相关的处理方法:
NetworkComms.AppendGlobalIncomingPacketHandler<LoginContract>("ReqLogin", IncomingLoginRequest);
private void IncomingLoginRequest(PacketHeader header, Connection connection, LoginContract loginContract)
{
try
{
string resMsg="";
//为了简单,这里不调用数据库,而是模拟一下登录
")
resMsg = "登录成功";
else
resMsg = "用户名密码错误";
//把返回结果写入到契约类中,后面返回给客户端
ResMsgContract contract = new ResMsgContract();
contract.Message = resMsg;
connection.SendObject("ResLogin", contract);
}
catch (Exception ex)
{
}
}
通过以上的写法,当服务器器收到消息类型为“ReqLogin"的消息时,会自动获取到相关的处理方法。
我们看一下背后的运行机制。
首先看注册语句:
NetworkComms.AppendGlobalIncomingPacketHandler<LoginContract>("ReqLogin", IncomingLoginRequest);
AppendGlobalIncomingPacketHandler()方法,把消息类型”ReqLogin"和处理方法“INcomingLoginRequest"添加到NetworkComms静态类的字典中: 在AppendGlobalIncomingPacketHander<T>方法中 ,我们的处理方法 IncomingLoginRequest 与 PacketHandlerCallBackDelegate<T>参数相对应。 来看一下PacketHandlerCallBackDelegate的定义
public delegate void PacketHandlerCallBackDelegate<T>(PacketHeader packetHeader, Connection connection, T incomingObject);
AppendGlobalIncomingPacketHandler()方法如下:
public static void AppendGlobalIncomingPacketHandler<T>(string packetTypeStr, PacketHandlerCallBackDelegate<T> packetHandlerDelgatePointer)
{
if (packetTypeStr == null) throw new ArgumentNullException("packetTypeStr", "Provided packetType string cannot be null.");
if (packetHandlerDelgatePointer == null) throw new ArgumentNullException("packetHandlerDelgatePointer", "Provided PacketHandlerCallBackDelegate<T> cannot be null.");
if (sendReceiveOptions == null) throw new ArgumentNullException("sendReceiveOptions", "Provided SendReceiveOptions cannot be null.");
lock (globalDictAndDelegateLocker)
{
if (globalIncomingPacketUnwrappers.ContainsKey(packetTypeStr))
{
//Make sure if we already have an existing entry that it matches with the provided
if (!globalIncomingPacketUnwrappers[packetTypeStr].Options.OptionsCompatible(sendReceiveOptions))
throw new PacketHandlerException("The proivded SendReceiveOptions are not compatible with existing SendReceiveOptions already specified for this packetTypeStr.");
}
else
globalIncomingPacketUnwrappers.Add(packetTypeStr, new PacketTypeUnwrapper(packetTypeStr, sendReceiveOptions));
//Ad the handler to the list
if (globalIncomingPacketHandlers.ContainsKey(packetTypeStr))
{
//Make sure we avoid duplicates
PacketTypeHandlerDelegateWrapper<T> toCompareDelegate = new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer);
bool delegateAlreadyExists = false;
foreach (var handler in globalIncomingPacketHandlers[packetTypeStr])
{
if (handler == toCompareDelegate)
{
delegateAlreadyExists = true;
break;
}
}
if (delegateAlreadyExists)
throw new PacketHandlerException("This specific packet handler delegate already exists for the provided packetTypeStr.");
//把处理方法添加到相关字典中
globalIncomingPacketHandlers[packetTypeStr].Add(new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer));
}
else
globalIncomingPacketHandlers.Add(packetTypeStr, new List<IPacketTypeHandlerDelegateWrapper>() { new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer) });
if (LoggingEnabled) logger.Info("Added incoming packetHandler for '" + packetTypeStr + "' packetType.");
}
}
字典:
static Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>> globalIncomingPacketHandlers = new Dictionary<string, List<IPacketTypeHandlerDelegateWrapper>>();
我们看到上面有一句:
PacketTypeHandlerDelegateWrapper<T> toCompareDelegate = new PacketTypeHandlerDelegateWrapper<T>(packetHandlerDelgatePointer);
看一下PacketTypeHandlerDelegateWrapper类,此类把处理方法作为参数。
我们看一下此类:
class PacketTypeHandlerDelegateWrapper<T> : IPacketTypeHandlerDelegateWrapper
{
NetworkComms.PacketHandlerCallBackDelegate<T> innerDelegate;
public PacketTypeHandlerDelegateWrapper(NetworkComms.PacketHandlerCallBackDelegate<T> packetHandlerDelegate)
{
this.innerDelegate = packetHandlerDelegate;
}
public object DeSerialize(MemoryStream incomingBytes, SendReceiveOptions options)
{
if (incomingBytes == null) return null;
//if (incomingBytes == null || incomingBytes.Length == 0) return null;
else
//{
//if (options.DataSerializer == null)
// throw new ArgumentNullException("options", "The provided options.DataSerializer was null. Cannot continue with deserialise.");
return options.DataSerializer.DeserialiseDataObject<T>(incomingBytes, options.DataProcessors, options.Options);
//}
}
public void Process(PacketHeader packetHeader, Connection connection, object obj)
{
innerDelegate(packetHeader, connection, (obj == null ? default(T) : (T)obj));
}
public bool Equals(IPacketTypeHandlerDelegateWrapper other)
{
if (innerDelegate == (other as PacketTypeHandlerDelegateWrapper<T>).innerDelegate)
return true;
else
return false;
}
public bool EqualsDelegate(Delegate other)
{
return other as NetworkComms.PacketHandlerCallBackDelegate<T> == innerDelegate;
}
}
感觉这一章写的不太清楚,水平有限,您可以自行阅读一下networkcomms2.3.1开源版本的源代码,获取会看的比较清晰:)
www.cnblogs.com/networkcomms
www.networkcomms.cn
c#网络通信框架networkcomms内核解析之九 自定义处理方法的运行机制的更多相关文章
- c#网络通信框架networkcomms内核解析 序言
NetworkComms网络通信框架序言 networkcomms是我遇到的写的最优美的代码,很喜欢,推荐给大家:) 基于networkcomms2.3.1开源版本( gplv3)协议,写了一些文章, ...
- c#网络通信框架networkcomms内核解析之十 支持优先级的自定义线程池
NetworkComms网络通信框架序言 本例基于networkcomms2.3.1开源版本 gplv3协议 如果networkcomms是一顶皇冠,那么CommsThreadPool(自定义线程池 ...
- c#网络通信框架networkcomms内核解析之八 数据包的核心处理器
NetworkComms网络通信框架序言 本文基于networkcomms2.3.1开源版本 gplv3协议 我们先回顾一个 c#网络通信框架networkcomms内核解析之六 处理接收到的二进制 ...
- c#网络通信框架networkcomms内核解析之一 消息传送
networkcomms.net 来自英国的网络通信框架 官方网址 www.networkcomms.net 中文网址www.networkcomms.cn 在网络通信程序中,本地的类或者对象,要传输 ...
- c#网络通信框架networkcomms内核解析之一 消息传送2
networkcomms.net 来自英国的网络通信框架 官方网址 www.networkcomms.net 中文网址www.networkcomms.cn 在网络通信程序中,本地的类或者对象,要传输 ...
- c#网络通信框架networkcomms内核解析之三 消息同步调用
networkcomms.net 来自英国的网络通信框架 官方网址 www.networkcomms.net 中文网址www.networkcomms.cn 客户端发送消息给服务器,服务器计算结果返回 ...
- c#网络通信框架networkcomms内核解析之六 处理接收到的二进制数据
本文基于networkcomms2.3.1开源版本 gplv3协议 在networkcomms通信系统中,服务器端收到某连接上的数据后,数据会暂时存放在"数据包创建器"(Pack ...
- xenomai内核解析之信号signal(一)---Linux信号机制
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 1. Linux信号 1.1注册信号处理函数 ...
- xenomai内核解析之信号signal(二)---xenomai信号处理机制
xenomai信号 上篇文章讲了linux的信号在内核的发送与处理流程,现在加入了cobalt核,Cobalt内核为xenomai线程提供了信号机制.下面一一解析xenomai内核的信号处理机制. 1 ...
随机推荐
- 使用ajax上传中遇到的问题
使用ajaxSubmit提交文件时,正确使用返回的json数据需要用eval在转化一下. 前台文件: $("#form1").ajaxSubmit({ url: 'QueryHan ...
- window.event
e = e || window.event是我们在做事件处理时候区分IE和其他浏览器事件对象时常用的写法.但是这行兼容性代码有没有必要出现在所有的事件句柄中呢?标准事件调用方式需要这行代码吗?下边我们 ...
- MVC @Html.TextBox 添加属性和样式
1.添加属性:@Html.TextBox("CnAddressmodify","", new { maxlength="90" }) 2.添 ...
- 夺命雷公狗-----React---12--添加类和样式
<!DOCTYPE> <html> <head> <meta charset="utf-8"> <title></ ...
- python 清楚数组重复字符串元素
l1 = ['bb','c','d','bb','c','a','a'] l2 = {}.fromkeys(l1).keys() print (l2)
- Android TextWatcher监控EditText中的输入内容并限制其输入字符个数
布局中EditText在android布局中经常用到,对EditText中输入的内容也经常需要进行限制,我们可以通过TextWatcher去观察输入框中输入的内容,作个笔记. 主布局: <?xm ...
- db2常用命令(1)
DB2常用命令 1.启动实例(db2inst1):实例相当于informix中的服务 db2start 2.停止实例(db2inst1): db2stop 3.列出所有实例(db2inst1) d ...
- Mac下安装LNMP(Nginx+PHP5.6)环境
[转自:http://avnpc.com/pages/install-lnmp-on-osx] 安装Homebrew 最近工作环境切换到Mac,所以以OS X Yosemite(10.10.1)为例, ...
- easyui DataGrid 工具类之 Utils class
import java.lang.reflect.InvocationTargetException;import java.text.ParseException;import java.text. ...
- python基本数据类型之集合set
一.集合的定义 set集合,是一个无序且不重复的元素集合. 集合对象是一组无序排列的可哈希的值,集合成员可以做字典中的键.集合支持用in和not in操作符检查成员,由len()内建函数得到集合的基数 ...