写自己的Socket框架(三)
在通信写完了以后,应用层接收到Socket抛上来的byte[],这个时候对于实际的写逻辑的开发者来说,这样的数据并不友好,我们就需要在应用层统一一个包的规则(应用层协议),处理完以后,然后再传给实际的逻辑层去处理。
以下是一个常用的Command模式。既接收到传递过来的包以后,根据Command(命令)来执行对应的Command(逻辑)。
我们假定我们的包(以下所有的包都指的是应用层的包,而非Socket层的包)分为 命令头/数据 两块。
public class InterUnit
{
public string Command;
public JToken Body;
}
因为采用Command模式,我们定义了一个接口ICommand
public interface ICommand
{
InterUnit Execute(InterUnit unit);
}
命令的Command,如何跟实际逻辑对应起来,常用的有Ioc,但是你也可以硬编码,我采用的是Attribute的方式,来对应起来。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CommandAttribute : Attribute
{
public CommandAttribute(string command)
{
this.Command = command;
} public string Command;
}
对应起来以后,那就需要在接到包的地方,去根据Command找到对应的Class来执行逻辑。
public class CommandFactory
{
private Dictionary<string, ICommand> _commandMap; public CommandFactory()
{
if (_commandMap == null)
{
_commandMap = new Dictionary<string, ICommand>();
}
} /// <summary>
/// 通过反射将标注了CommandAttribute的实例,放入字典。
/// 不需要等到需要调用时,才去动态的注入。
/// </summary>
/// <param name="assembly"></param>
public void Init(params string[] assembly)
{
if (assembly != null)
{
foreach (string s in assembly)
{
var ass = Assembly.Load(s);
if (ass != null)
{
var types = ass.GetTypes();
foreach (var type in types)
{
CommandAttribute attr = type.GetCustomAttribute(typeof(CommandAttribute), false) as CommandAttribute;
if (attr != null)
{
if (attr.Command == null || attr.Command.Length == )
{
_commandMap[type.Name] = Activator.CreateInstance(type) as ICommand;
}
else
{
_commandMap[attr.Command] = Activator.CreateInstance(type) as ICommand;
}
}
}
}
}
}
} public void ExecuteCommand(SocketSession session, InterUnit unit)
{
if(_commandMap.ContainsKey(unit.Command))
{
ICommand command = _commandMap[unit.Command];
var rtv = command.Execute(unit);
if (rtv != null)
{
session.Send(BsonHelper.ToBson<InterUnit>(unit));
}
}
}
}
我在这里采用的是Bson的格式,作为数据来传递。
有一个地方需要注意的就是,在Send的时候,实际上我们并没有定义Socket的包的格式,因为在协议的地方已经处理了这个事情,会将你发送过去的数据,自动加上包头。
public interface IProtocol
{
byte[] OnDataReceivedCallBack(byte[] data, ref int offset); byte[] OnDataSendBefore(byte[] data);
} public class DefaultProtocol : IProtocol
{
public byte[] OnDataReceivedCallBack(byte[] data, ref int offset)
{
int length = BitConverter.ToInt32(data, offset);
int package_head = ;
int package_length = length + package_head;
byte[] buffer = null;
if (length > )
{
if (offset + package_length <= data.Length)
{
buffer = new byte[length];
Array.Copy(data, offset + package_head, buffer, , length);
offset += package_length;
}
}
else
{
offset = -;
}
return buffer;
} public byte[] OnDataSendBefore(byte[] data)
{
int length = data.Length;
var head = BitConverter.GetBytes(length);
byte[] buffer = new byte[data.Length + head.Length];
Buffer.BlockCopy(head, , buffer, , head.Length);
Buffer.BlockCopy(data, , buffer, head.Length, data.Length); return buffer;
}
}
写自己的Socket框架(三)的更多相关文章
- linux可用的跨平台C# .net standard2.0 写的高性能socket框架
能在window(IOCP)/linux(epoll)运行,基于C# .net standard2.0 写的socket框架,可使用于.net Framework/dotnet core程序集,.使用 ...
- 写自己的Socket框架(一)
本系列仅介绍可用于生产环境的C#异步Socket框架,如果您在其他地方看到类似的代码,不要惊讶,那可能就是我在参考开源代码时,直接“剽窃”过来的. 1.在脑海里思考一下整个socket的链接的处理流程 ...
- 写自己的socket框架(二)
1.开始正常监听以后,就要开始接受数据了,整体流程图如下: 2.上一节看到我们在程序初始化的时候,初始化了很多个SocketConnection,用于管理客户端的链接,那应用层如何来操作,又什么时候来 ...
- Workerman:PHP的socket框架
hi,我们今天来讲讲Workerman,什么是Workerman呢? 看看官网上的介绍 Workerman是一款开源高性能异步PHP socket框架.支持高并发,超高稳定性,被广泛的用于手机app. ...
- ZYSocket 4.3.5 SOCKET框架组 发布[NEW]
最新代码请到 github: https://github.com/luyikk/ZYSOCKET 更新 4.3.5更新说明: 修复各种BUG. 重写了一份 protobuf-net 有什么用呢,不需 ...
- Jersey框架三:Jersey对HTTPS的支持
Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...
- atitit.软件开发--socket框架选型--netty vs mina j
atitit.软件开发--socket框架选型--netty vs mina j . Netty是由JBOSS提供的一个java开源框架 Apache mina 三.文档比较 mina文档多,,, 好 ...
- 从零开始实现一个简易的Java MVC框架(三)--实现IOC
Spring中的IOC IoC全称是Inversion of Control,就是控制反转,他其实不是spring独有的特性或者说也不是java的特性,他是一种设计思想.而DI(Dependency ...
- 如果你想写自己的Benchmark框架
目录 简介 八条军规 第一条军规 第二条军规 第三条军规 第四条军规 第五条军规 第六条军规 第七条军规 最后一条军规 总结 简介 使用过JMH的同学一定会惊叹它的神奇.JMH作为一个优秀的Bench ...
随机推荐
- mapreduce多文件输出的两方法
mapreduce多文件输出的两方法 package duogemap; import java.io.IOException; import org.apache.hadoop.conf ...
- 详解树莓派Model B+控制蜂鸣器演奏乐曲
步进电机以及无源蜂鸣器这些都需要脉冲信号才能够驱动,这里将用GPIO的PWM接口驱动无源蜂鸣器弹奏乐曲,本文基于树莓派Mode B+,其他版本树莓派实现时需参照相关资料进行修改! 1 预备知识 1.1 ...
- 异步编程 In .NET
概述 在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的尝试.今天我们再来回答一下这个问题,同时我们 ...
- 如何利用ETW(Event Tracing for Windows)记录日志
ETW是Event Tracing for Windows的简称,它是Windows提供的原生的事件跟踪日志系统.由于采用内核(Kernel)层面的缓冲和日志记录机制,所以ETW提供了一种非常高效的事 ...
- IE8/9 JQuery.Ajax 上传文件无效
IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...
- 反应器(Reactor)和主动器(Proactor)
网络方面用的比较多的库是libevent和boost.asio,两者都是跨平台的.其中libevent是基于Reactor实现的,而boost.asio是基于Proactor实现的.Reactor和P ...
- javascript高性能编程-算法和流程控制
代码整体结构是执行速度的决定因素之一. 代码量少不一定运行速度快, 代码量多也不一定运行速度慢. 性能损失与代码组织方式和具体问题解决办法直接相关. 倒序循环可以提高性能,如: ...
- 易用BPM时代,企业如何轻松驾驭H3?
众所周知,BPM作为企业发展的推动力,能敏捷高效的融合业务流程和信息资源.通过综合考虑流程的成本.效率.质量等方面因素,用IT系统将调整后的流程固化下来,从而降低企业管理成本,提高内部运营效率,提升企 ...
- PHP安装
工具 http://www.cnblogs.com/xiwang6428/p/4315049.html http://www.iteye.com/news/22672 1 安装:sudo apt-ge ...
- 我的MYSQL学习心得(十二) 触发器
我的MYSQL学习心得(十二) 触发器 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数 ...