600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 详细介绍C#常用协议实现模版及FixedSizeReceiveFilter的示例代码

详细介绍C#常用协议实现模版及FixedSizeReceiveFilter的示例代码

时间:2021-09-28 09:08:15

相关推荐

详细介绍C#常用协议实现模版及FixedSizeReceiveFilter的示例代码

后端开发|C#.Net教程

C#,常用协议

后端开发-C#.Net教程

本文主要介绍了常用协议实现模版及FixedSizeReceiveFilter示例。具有很好的参考价值,下面跟着小编一起来看下吧

工作室引导源码,ubuntu 系统的网络,爬虫爬取滴滴,php imgpng,hyein seo衣服lzw

Socket里面的协议解析是Socket通讯程序设计中最复杂的地方,如果你的应用层协议设计或实现不佳,Socket通讯中常见的粘包,分包就难以避免。SuperSocket内置了命令行格式的协议CommandLineProtocol,如果你使用了其它格式的协议,就必须自行实现自定义协议CustomProtocol。看了一篇文档之后, 你可能会觉得用 SuperSocket 来实现你的自定义协议并不简单。 为了让这件事变得更容易一些, SuperSocket 提供了一些通用的协议解析工具, 你可以用他们简单而且快速的实现你自己的通信协议:

asp oa办公系统源码下载,vscode消除通知,ubuntu pywt,tomcat连接并发,sqlite打开微信.db,360插件源码,后端程序员的前端框架,图片爬虫vip激活码,免费国外php空间,潍坊seo技术外包,手机网站的模板下载 迅雷下载,html5网页制作教程,电商网站模板引擎lzw

TerminatorReceiveFilter (SuperSocket.SocketBase.Protocol.TerminatorReceiveFilter, SuperSocket.SocketBase) —结束符协议

电商聊天源码,vscode游戏插件,lxd ubuntu,tomcat输出换行,sqlite 执行脚本,获取源代码插件,LayUI前端框架开发视频,网络爬虫基本爬行策略,php上传乱码,谷歌seo知识总结,织梦网站首页标签,网页psd模版下载,互联网 的模板免费下载lzw

CountSpliterReceiveFilter (SuperSocket.Facility.Protocol.CountSpliterReceiveFilter, SuperSocket.Facility)—固定数量分隔符协议

FixedSizeReceiveFilter (SuperSocket.Facility.Protocol.FixedSizeReceiveFilter, SuperSocket.Facility)—固定请求大小协议

BeginEndMarkReceiveFilter (SuperSocket.Facility.Protocol.BeginEndMarkReceiveFilter, SuperSocket.Facility)—带起止符协议

FixedHeaderReceiveFilter (SuperSocket.Facility.Protocol.FixedHeaderReceiveFilter, SuperSocket.Facility)—头部格式固定并包含内容长度协议

1、TerminatorReceiveFilter结束符协议

结束符协议和命令行协议类似,一些协议用结束符来确定一个请求.例如, 一个协议使用两个字符 “##” 作为结束符, 于是你可以使用类 “TerminatorReceiveFilterFactory”:

结束符协议TerminatorProtocolServer :

public class TerminatorProtocolServer : AppServer{ public TerminatorProtocolServer() : base(new TerminatorReceiveFilterFactory("##")) { }}

基于TerminatorReceiveFilter实现你的接收过滤器(ReceiveFilter):

public class YourReceiveFilter : TerminatorReceiveFilter{ //More code}

实现你的接收过滤器工厂(ReceiveFilterFactory)用于创建接受过滤器实例:

public class YourReceiveFilterFactory : IReceiveFilterFactory{ //More code}

2、CountSpliterReceiveFilter 固定数量分隔符协议

有些协议定义了像这样格式的请求 “#part1#part2#part3#part4#part5#part6#part7#”. 每个请求有7个由 ‘#’ 分隔的部分. 这种协议的实现非常简单:

/// public class CountSpliterAppServer : AppServer{ public CountSpliterAppServer() : base(new CountSpliterReceiveFilterFactory((byte)#, 8)) //8个分隔符,7个参数。除使用默认的过滤工厂,还可以参照上一个实例定制协议 { }}

3、FixedSizeReceiveFilter 固定请求大小协议

在这种协议之中, 所有请求的大小都是相同的。如果你的每个请求都是有8个字符组成的字符串,如”HUANG LI”, 你应该做的事就是想如下代码这样实现一个接收过滤器(ReceiveFilter):

class MyReceiveFilter : FixedSizeReceiveFilter{ public MyReceiveFilter() : base(8) //传入固定的请求大小 { } protected override StringRequestInfo ProcessMatchedRequest(byte[] buffer, int offset, int length, bool toBeCopied) { //TODO: 通过解析到的数据来构造请求实例,并返回 }}

然后在你的 AppServer 类中使用这个接受过滤器 (ReceiveFilter):

public class MyAppServer : AppServer{ public MyAppServer() : base(new DefaultReceiveFilterFactory()) //使用默认的接受过滤器工厂 (DefaultReceiveFilterFactory) { }}

4、BeginEndMarkReceiveFilter 带起止符协议

在这类协议的每个请求之中 都有固定的开始和结束标记。例如, 我有个协议,它的所有消息都遵循这种格式 “&xxxxxxxxxxxxxx#”。因此,在这种情况下, “&” 是开始标记, “#” 是结束标记,于是你的接受过滤器可以定义成这样:

class MyReceiveFilter : BeginEndMarkReceiveFilter{ //开始和结束标记也可以是两个或两个以上的字节 private readonly static byte[] BeginMark = new byte[] { (byte)& }; private readonly static byte[] EndMark = new byte[] { (byte)# }; public MyReceiveFilter() : base(BeginMark, EndMark) //传入开始标记和结束标记 { } protected override StringRequestInfo ProcessMatchedRequest(byte[] readBuffer, int offset, int length) { //TODO: 通过解析到的数据来构造请求实例,并返回 }}

然后在你的 AppServer 类中使用这个接受过滤器 (ReceiveFilter):

public class MyAppServer : AppServer{ public MyAppServer() : base(new DefaultReceiveFilterFactory()) //使用默认的接受过滤器工厂 (DefaultReceiveFilterFactory) { }}

5、FixedHeaderReceiveFilter 头部格式固定并包含内容长度协议

这种协议将一个请求定义为两大部分, 第一部分定义了包含第二部分长度等等基础信息. 我们通常称第一部分为头部.

例如, 我们有一个这样的协议: 头部包含 6 个字节, 前 4 个字节用于存储请求的名字, 后两个字节用于代表请求体的长度:

/// +-------+---+-------------------------------+/// |request| l ||/// | name | e | request body|/// | (4) | n ||/// | |(2)||/// +-------+---+-------------------------------+

使用 SuperSocket, 你可以非常方便的实现这种协议:

class MyReceiveFilter : FixedHeaderReceiveFilter{ public MyReceiveFilter() : base(6) { } protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { return (int)header[offset + 4] * 256 + (int)header[offset + 5]; } protected override BinaryRequestInfo ResolveRequestInfo(ArraySegment header, byte[] bodyBuffer, int offset, int length) { return new BinaryRequestInfo(Encoding.UTF8.GetString(header.Array, header.Offset, 4), bodyBuffer.CloneRange(offset, length)); }}

你需要基于类FixedHeaderReceiveFilter实现你自己的接收过滤器.

传入父类构造函数的 6 表示头部的长度;

方法”GetBodyLengthFromHeader(…)” 应该根据接收到的头部返回请求体的长度;

方法 ResolveRequestInfo(….)” 应该根据你接收到的请求头部和请求体返回你的请求类型的实例.

实际使用场景:

到这里五种协议的模板你都已经了解了一遍,并且知道了相关的格式处理。接下来看一个网络示例:

通讯协议格式:

在看到上图协议是在纠结客户端发送16进制,服务器怎么接收,16进制的报文如下:

26 01 00 19 4E 4A 30 31 31 01 44 41 31 31 32 00 07 00 00 00 00 00 00 34 23

16进制也好,10进制也好,其他的进制也好,最终都是转换成byte[],其实在处理数据时,发送过去的数据都是可以转换成为byte[]的,所以服务的只要解析byte[]数组就行了。按照协议来解析就能得到想要的数据。下面使用FixedSizeReceiveFilter的例子,代码如下:

根据上面的通讯协议,开始来实现解析:

第一步、定义一个和协议合适的数据结构

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-23 21:12:30* * 描述说明:协议数据包** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLData { /// public char Head { get; set; } /// public byte Ping { get; set; } /// public ushort Lenght { get; set; } /// public uint FID { get; set; } /// public byte Type { get; set; } /// public uint SID { get; set; } /// public ushort SendCount { get; set; } /// public byte[] Retain { get; set; } /// public byte Check { get; set; } /// public char End { get; set; } public override string ToString() { return string.Format("开始符号:{0},包数据:{1},数据长度:{2},终端ID:{3},目标类型:{4},转发终端ID:{5},发送包计数:{6},保留字段:{7},异或校验:{8},结束符号:{9}", Head, Ping, Lenght, FID, Type, SID, SendCount, Retain, Check, End); } }}HLData

第二步、建立一个RequestInfo来给server数据接收

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using SuperSocket.SocketBase.Protocol;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-22 21:03:31* * 描述说明:数据请求** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLProtocolRequestInfo : RequestInfo { public HLProtocolRequestInfo(HLData hlData) { //如果需要使用命令行协议的话,那么命令类名称HLData相同 Initialize("HLData", hlData); } }}HLProtocolRequestInfo 类

第三步、FixedSize协议解析

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using SuperSocket.SocketBase.Protocol;using SuperSocket.Facility.Protocol;using mon;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-22 21:06:01* * 描述说明:协议解析类,固定请求大小的协议** 修改历史:*******************************************************************/namespace SuperSocketDemo{ /// public class HLProtocolReceiveFilter : FixedSizeReceiveFilter { public HLProtocolReceiveFilter() : base(25)//总的字节长度 1+1+2+5+1+5+2+6+1+1 = 25 { } protected override HLProtocolRequestInfo ProcessMatchedRequest(byte[] buffer, int offset, int length, bool toBeCopied) { var HLData = new HLData(); HLData.Head = (char)buffer[offset];//开始标识的解析,1个字节 HLData.Ping = buffer[offset + 1];//数据,从第2位起,只有1个字节 HLData.Lenght = BitConverter.ToUInt16(buffer, offset + 2);//数据长度,从第3位开始,2个字节 HLData.FID = BitConverter.ToUInt32(buffer, offset + 4);//本终端ID,从第5位开始,5个字节 HLData.Type = buffer[offset + 9];//目标类型,从第10位开始,1个字节 HLData.SID = BitConverter.ToUInt32(buffer, offset + 10);//转发终端ID,从第11位开始,5个字节 HLData.SendCount = BitConverter.ToUInt16(buffer, offset + 15);//发送包计数,从第16位开始,2个字节 HLData.Retain = buffer.CloneRange(offset + 17, 6);//保留字段,从18位开始,6个字节 HLData.Check = buffer[offset + 23];//异或校验,从24位开始,1个字节 HLData.End = (char)buffer[offset + 24];//结束符号,从第25位开始,一个字节 return new HLProtocolRequestInfo(HLData); } }}HLProtocolReceiveFilter类

第四步、建立协议工厂HLReceiveFilterFactory

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using SuperSocket.SocketBase;using SuperSocket.SocketBase.Protocol;using ;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-23 :22:01:25* * 描述说明:协议工厂** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLReceiveFilterFactory: IReceiveFilterFactory { public IReceiveFilter CreateFilter(IAppServer appServer, IAppSession appSession, IPEndPoint remoteEndPoint) { return new HLBeginEndMarkReceiveFilter(); } }}HLReceiveFilterFactory类

第五步、自定义HLProtocolSession继承AppSession

using SuperSocket.SocketBase;using SuperSocket.SocketBase.Protocol;using System;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-22 21:15:11* * 描述说明:自定义HLProtocolSession** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLProtocolSession : AppSession { protected override void HandleException(Exception e) { } }}HLProtocolSession类

第六步、自定义HLProtocolServer继承AppServer

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using SuperSocket.SocketBase;using SuperSocket.SocketBase.Protocol;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-22 21:16:57* * 描述说明:自定义server** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLProtocolServer : AppServer { ///public HLProtocolServer(): base(new HLReceiveFilterFactory()){ } }}HLProtocolServer类

第七步、加上起止符协议HLBeginEndMarkReceiveFilter

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using mon;using SuperSocket.Facility.Protocol;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-23 22:07:03* * 描述说明:带起止符的协议, "&" 是开始标记, "#" 是结束标记,开始结束标记由自己定义** 修改历史:*******************************************************************/namespace SuperSocketDemo{ public class HLBeginEndMarkReceiveFilter : BeginEndMarkReceiveFilter { private readonly static char strBegin = &; private readonly static char strEnd = #; //开始和结束标记也可以是两个或两个以上的字节 private readonly static byte[] BeginMark = new byte[] { (byte)strBegin }; private readonly static byte[] EndMark = new byte[] { (byte)strEnd }; public HLBeginEndMarkReceiveFilter() : base(BeginMark, EndMark) { } ///////////////protected override HLProtocolRequestInfo ProcessMatchedRequest(byte[] readBuffer, int offset, int length) {var HLData = new HLData();HLData.Head = strBegin;//自己定义开始符号HLData.Ping = readBuffer[offset];//数据,从第1位起,只有1个字节HLData.Lenght = BitConverter.ToUInt16(readBuffer, offset + 1);//数据长度,从第2位开始,2个字节HLData.FID = BitConverter.ToUInt32(readBuffer, offset + 3);//本终端ID,从第4位开始,5个字节HLData.Type = readBuffer[offset + 8];//目标类型,从第9位开始,1个字节HLData.SID = BitConverter.ToUInt32(readBuffer, offset + 9);//转发终端ID,从第10位开始,5个字节HLData.SendCount = BitConverter.ToUInt16(readBuffer, offset + 14);//发送包计数,从第15位开始,2个字节HLData.Retain = readBuffer.CloneRange(offset + 16, 6);//保留字段,从17位开始,6个字节HLData.Check = readBuffer[offset + 22];//异或校验,从23位开始,1个字节HLData.End = strEnd;//结束符号,自己定义return new HLProtocolRequestInfo(HLData); } }}HLBeginEndMarkReceiveFilter类

第八步、服务启动和停止

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using SuperSocket.SocketBase;using SuperSocket.SocketBase.Protocol;using SuperSocket.SocketEngine;/***************************************************************** 作者:黄昏前黎明后* CLR版本:4.0.30319.42000* 创建时间:-01-19 00:02:17* * 描述说明:服务启动和停止入口 ** 修改历史: -01-19 调整自定义mysession和myserver* -01-23 通讯协议解析,直接使用入口注册事件******************************************************************/namespace SuperSocketDemo{ class Program { //////static void Main(string[] args) {Console.WriteLine("请按任何键进行启动SuperSocket服务!");Console.ReadKey();Console.WriteLine();var HLProtocolServer = new HLProtocolServer();// 设置端口号int port = ;//启动应用服务端口if (!HLProtocolServer.Setup(port)) //启动时监听端口{ Console.WriteLine("服务端口启动失败!"); Console.ReadKey(); return;}Console.WriteLine();//注册连接事件HLProtocolServer.NewSessionConnected += HLProtocolServer_NewSessionConnected;//注册请求事件HLProtocolServer.NewRequestReceived += HLProtocolServer_NewRequestReceived;//注册Session关闭事件HLProtocolServer.SessionClosed += HLProtocolServer_SessionClosed;//尝试启动应用服务if (!HLProtocolServer.Start()){ Console.WriteLine("服务启动失败!"); Console.ReadKey(); return;}Console.WriteLine("服务器状态:" + HLProtocolServer.State.ToString());Console.WriteLine("服务启动成功,请按E停止服务!");while (Console.ReadKey().KeyChar != E){ Console.WriteLine(); continue;}//停止服务HLProtocolServer.Stop();Console.WriteLine("服务已停止!");Console.ReadKey(); } static void HLProtocolServer_SessionClosed(HLProtocolSession session, SuperSocket.SocketBase.CloseReason value) {Console.WriteLine(session.RemoteEndPoint.ToString() + "连接断开. 断开原因:" + value); } static void HLProtocolServer_NewSessionConnected(HLProtocolSession session) {Console.WriteLine(session.RemoteEndPoint.ToString() + " 已连接."); } /////////private static void HLProtocolServer_NewRequestReceived(HLProtocolSession session, HLProtocolRequestInfo requestInfo) {Console.WriteLine();Console.WriteLine("数据来源: " + session.RemoteEndPoint.ToString());Console.WriteLine("接收数据内容:"+requestInfo.Body); } }}Program类

通讯协议需要使用小工具进行调试,本人使用的是TCP/UDP端口调试工具SocketTool V2.大家可以直接进行下载。使用HEX模式进行发送16进制报文,服务器输出结果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。