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 ...
随机推荐
- MVC Action返回Json
Action [HttpPost] public ActionResult Edit(Study_CourseHourModel model) { ...
- SQL中的charindex函数与reverse函数用法
----------------------首先介绍charindex函数----------------------------- ...
- Qt之重写QLabel类
在mylabel.h 文件中#ifndef MYLABEL_H#define MYLABEL_H #include <QLabel>/*重新实现QLabel类,使其支持点击事件*/clas ...
- mui记录
事件addEventListener()绑定事件的对象方法.addEventListener()含有三个参数,一个是事件名称,另一个是事件执行的函数,最后一个是事件捕获.obj.addEventLis ...
- wex5 教程 之 图文讲解 bind-css和bind-sytle的异同
wex5作为网页开发利器,在前台UI数据交互设计中大量使用了绑定技术,即官方视频教学中也提到了KO,实质是数据绑定与追踪.在前台组件的属性中,为我们提供了两个重要的样式绑定属性,bind-css和bi ...
- mysql常用命令(3)
一.启动与关闭 1.1 Linux下启动mysql 的命令: a. rpm包安装:service mysqld start b. 源码包安装:/usr/local/mysql/bin/mysqld_s ...
- mina IoBuffer 常用方法
Limit(int) 如果position>limit, position = limit,如果mark>limit, 重置mark Mark() 取当前的position的快照标记mar ...
- (4) 深入理解Java Class文件格式(三)
转载:http://blog.csdn.net/zhangjg_blog/article/details/21557357 首先, 让我们回顾一下关于class文件格式的之前两篇博客的主要内容. 在 ...
- MySQL查询语句
来源于网络... Sutdent表的定义 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 学号 INT(10) 是 否 是 是 是 Name 姓名 VARCHAR(20) 否 否 是 ...
- [多校联考2 T3] 排列 (DP)
DP Description 对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用 I 表示,反之这个位置是下降的,用 D表示.如排列 3,1,2,7,4,6,5 可以 ...