我们来做一个头为6位报文总长度,并且长度不包含长度域自身的例子。比如这样的Socket报文000006123456

  1. 添加SuperSocket.Engine,直接使用Nuget搜索SuperSocket.Engine安装即可,依赖项为SuperSocket和log4net。

    这里注意,SuperSocket 2.0以后没有SuperSocket.Engine了,直接使用SuperSocket即可,但是由于我这次是在.net framework 4.7的环境下使用,SuperSocket 2.0最低支持.net standard 2.1即只能支持.net core已经.net 5 6了,所以这里没法使用。

  2. 创建一个ReceiveFilter。

public class LengthReceiveFilter: FixedHeaderReceiveFilter<StringRequestInfo>
{
public LengthReceiveFilter() : base(6)
{
} protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
{
return int.Parse(Encoding.Default.GetString(header, offset, length));
} protected override StringRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
{
return new StringRequestInfo("", Encoding.UTF8.GetString(bodyBuffer, offset, length), null);
}
}

这里我们需要重写两个方法,以及调用一下父类的构造方法。

public LengthReceiveFilter() : base(6)这里的6代表头长度为6位。

protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)方法中,header即为截取到的6位报文头的byte数组,offset是偏移量,length是长度,返回值为报文的总长度。

由于我们报文格式中前六位为数字格式的报文长度,所以我们可以直接用int.Parse(Encoding.Default.GetString(header, offset, length))来获取报文长度,如果长度包含长度本身,那要在-6,这里返回的是报文体的长度,如果返回的长度过长,则会不断的等待后续包。

protected override StringRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)是真正的解析方法,

把我们的报文转换成RequestInfo。这里我们直接用StringRequestInfo,就是把报文简单粗暴的直接转换成字符串。其中header就是我们的报文头的数据,如果这里还需要报文头就从header中拿,bodyBuffer就是我们的报文内容,offset是偏移量,length是长度。

如果我们在GetBodyLengthFromHeader方法中返回的长度比报文体还要长,那么就一直不会走到ResolveRequestInfo这个方法中。

  1. 新建一个MyAppServer继承AppServer

public class MyAppServer : AppServer
{
public MyAppServer() : base(new DefaultReceiveFilterFactory<LengthReceiveFilter,StringRequestInfo>())
{ }
}

这里我们直接用DefaultReceiveFilterFactory这个内置的工厂来绑定我们的Filter

  1. 启动服务器

private void button1_Click(object sender, EventArgs e)
{
AppServer appServer = new MyAppServer(); appServer.NewSessionConnected += session =>
{ }; appServer.NewRequestReceived += (session, info) =>
{
MessageBox.Show(info.Body);
session.Send("hello");
session.Close();
}; if (!appServer.Setup(1234))
{
MessageBox.Show("服务器设置失败");
return;
} if (!appServer.Start())
{
MessageBox.Show("服务器启动失败");
return;
} }

我们可以直接new MyAppServer来创建服务器。Setup方法的参数是端口号,我们使用appServer.Setup(1234)即把SocketServer监听的端口号设置为1234,appServer.Start()正式开启服务器。

appServer.NewSessionConnected是有新客户端连接上来的事件,这时候我们可以给客户端发送欢迎信息,或者执行一些其他操作。

appServer.NewRequestReceived是接收到新消息的事件,我们在这里可以拿到RequestInfo,从而获取到对应的信息。并且可以直接通过Send方法来返回消息。

这里需要注意的是如果Send直接使用字符串重载,那么会使用默认的编码格式,如果报文时UTF-8的,那么建议先用Encoding.UTF8.GetBytes转成byte数组,然后用Send的数组重载来发送内容。

  1. 关闭服务器

appServer.Stop();

即可关闭服务器。

SuperSocket 1.6 创建一个简易的报文长度在头部的Socket服务器的更多相关文章

  1. 依赖注入[5]: 创建一个简易版的DI框架[下篇]

    为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]> ...

  2. 依赖注入[4]: 创建一个简易版的DI框架[上篇]

    本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章(<控制反转>.<基于IoC的设计模式>和< 依赖注入模式>)从纯理论的角度 ...

  3. .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]

    原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...

  4. 使用Python创建一个简易的Web Server

    Python 2.x中自带了SimpleHTTPServer模块,到Python3.x中,该模块被合并到了http.server模块中.使用该模块,可以快速创建一个简易的Web服务器. 我们在C:\U ...

  5. 如何使用Java AWT 创建一个简易计算器

    摘要:手把手教你使用 Java AWT 创建一个简易计算器. 本文分享自华为云社区<手把手教你使用 Java AWT 创建一个简易计算器>,作者:海拥 . 关于AWT AWT (抽象窗口工 ...

  6. 用three.js创建一个简易的天空盒

    本文创建的天空盒是用六张图片来创建的.笔者会论述两种方法来创建,都是最简单基本的方法,不涉及着色器的使用.一种是创建一个盒子,然后将图片作为盒子6个面的纹理贴上来创建.另一种则是简单的将纹理作为场景的 ...

  7. .NET CORE学习笔记系列(2)——依赖注入[5]: 创建一个简易版的DI框架[下篇]

    为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在上篇中我们介绍了Cat的基本编程模式,接下来我们就来聊聊Cat的 ...

  8. Unity创建一个简易的弹簧(弹动)效果

    参考文章:http://www.cnblogs.com/SkyD/archive/2008/09/05/1284778.html 主要依据胡克公式F=-k·x.这里k是倔度系数,可以理解为k值越大弹性 ...

  9. python基础[18]——使用django创建一个简易的博客网站

    一.页面实现 index.html base.html post.html header.html footer.html <!-- index.html--> {% extends 'b ...

随机推荐

  1. 11.Flink实时项目之支付宽表

    支付宽表 支付宽表的目的,最主要的原因是支付表没有到订单明细,支付金额没有细分到商品上, 没有办法统计商品级的支付状况. 所以本次宽表的核心就是要把支付表的信息与订单明细关联上. 解决方案有两个 一个 ...

  2. Git删除已提交的文件

    Git删除已提交的文件 Git删除已提交的文件 定位文件 删除文件 参考链接 昨天通过Git Bash提交代码的时候遇到了由于单个文件大小超过100M,导致代码上传失败的问题.考虑到那个大文件是用于训 ...

  3. 算法篇(1) KMP JS实现最优查找子串

    var strStr = function (haystack, needle) { let i=0, j = 0; let length = haystack.length; let next = ...

  4. XCTF练习题---MISC---Hidden-Message

    XCTF练习题---MISC---Hidden-Message flag:Heisenberg 解题步骤: 1.观察题目,下载附件 2.拿到手以后发现是一个数据包格式,打开看一下 3.查看UDP流,并 ...

  5. ucore lab3 虚拟内存管理 学习笔记

    做个总结,这节说是讲虚拟内存管理,大部分的时间都在搞SWAP机制和服务于此机制的一些个算法.难度又降了一截. 不过现在我的电脑都16G内存了,能用完一半的情景都极少见了,可能到用到退休都不见得用的上S ...

  6. socket编程实现tcp服务器_C/C++

    1. 需求分析 实现一个回声服务器的C/S(客户端client/服务器server)程序,功能为客户端连接到服务器后,发送一串字符串,服务器接受信息后,返回对应字符串的大写形式给客户端显示. 例如: ...

  7. Linux vs Unix - Linux与Unix到底有什么不同?

    来自:Linux迷链接:https://www.linuxmi.com/linux-vs-unix.html Linux和Unix这两个术语可以互换地用来指同一操作系统.这在很大程度上是由于他们惊人的 ...

  8. CPU缓存L1/L2/L3工作原理

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 一.前言 在过去的几年中,计算机处理器取得了相当大的进步 ...

  9. Docker系列教程04-Docker构建镜像的三种方式

    简介 创建镜像的方法主要有三种:基于已有镜像的容器创建.基于本地模板导入.基于Dockerfile创建. 今天就逐一讲述为大家讲述,如何构建属于自己的docker镜像. 1.基于容器构建镜像 基于已有 ...

  10. JDBC:加载数据库驱动、连接数据库(详细讲解)

    加载数据库驱动: 1)由于Java是一个纯面向对象语言,任何事物在其中都必须抽象成类或者类对象,数据库也不例外,JDBC同样也把数据库抽象成面向对象的结构: 2)JDBC将整个数据库驱动器在底层抽象成 ...