SuperSocket 介绍

时间:2022-10-17 00:29:44

一、总体介绍

SuperSocket 是一个轻量级的可扩展的 Socket 开发框架,由江振宇先生开发。

官方网站:http://www.supersocket.net/

1、SuperSocket具有如下特点:

  • 简单易用,只需要几个类就能创建出健壮的Socket服务器端程序
  • 性能优良, 稳定可靠
  • 支持各种协议, 内置的协议解析工具让你把实现通信协议这种复杂的工作变得很简单
  • 自动支持SSL/TLS传输层加密
  • 强大,灵活而且可扩展的配置让你开发Socket服务器省时省力
  • 支持多个socket服务器实例运行, 而且支持多个服务器实例的隔离
  • SuperSocket能以控制台或者Windows服务形式运行。一个脚本就能将SuperSocket安装成服务
  • 灵活的日志策略能够记录大部分socket活动
  • 支持UDP
  • 支持IPv6
  • 支持Windows Azure
  • 支持Linux/Unix操作系统(通过Mono 2.10或以上版本)
  • 内置可直接使用的Flash/Silverlight Socket策略服务器

2、SuperSocket应对项目需求特点:

  1.      开源,基于Apache 2.0协议,可以免费使用到商业项目.
  2.      高性能的事件驱动通信.
  3.      会话级别的发送队列能够让你通过会话并发的发送数据,并保持高性能和可控性.
  4.      强大且高性能的协议解析实现工具帮你简化了网络数据的分析工作.
  5.      轻量级意味着组件可以*选择使用,可根据环境变化变更.

3、SuperSocket的架构和设计

可以在官方的中文文档查询到http://docs.supersocket.net/v1-6/zh-CN/Architecture-Diagrams

  1. 每个连接的客户端都以Session的方式管理,发送数据给客户端也通过Session的Send方法,
  2. 每个客户端发过来的数据流都经过ReceiveFilter过滤器(这里即可自定义协议或者使用自带的一些帧过滤器)到ReqestInfo。
  3. ReqestInfo包含了该条数据内容,当然如果是自定义的协议,可以实现自己的ReqestInfo,把数据包内容直接装入帧对象。

SuperSocket 层次示意图

SuperSocket层次解析:

  1. 设备层:基于flash和SilverLight的策略服务器和基于接收过滤器的协议实施。
  2. 应用层:可扩展的应用程序服务:包括多种API集成。会话容器和命令框架。
  3. 套接字层: 通过传输协议TCP和UDP的事件驱动套接字服务。

SuperSocket 介绍

SuperSocket 请求处理模型示意图

模型解析:

  1. 客户端携带数据流与Server端Socket Listener建立连接之后,SuperSocket 服务就将这一个连接视为一个Session会话。表示客户端和服务器端的一个逻辑连接,数据的收发都是在这个Session中进行处理的(此过程中的数据流为二进制数据)。
  2. 携带数据流的Session通过默认或者自定的接受过滤器将过滤后的数据传递到RequestInfo对象。每一个客户端对象都得实例化一个RequestInfo类,将接收到的二进制流转换成请求的实例。
  3. 根据RequestInfo执行Command命令,一个Command 包含一个Session和RequestInfo,在Command中根据需求解析数据。也可通过Session向客户端发送数据,例如有些DTU或者RTU设备需要发送指令才能返回数据。

SuperSocket 介绍

SuperSocket 对象模型图示意图

模型解析:

  1. 应用服务AppServer 包括命令Commands, 会话容器Session contaioner。
  2. 对象层次:基本配置Config->命令过滤器Command Filters->日志和日志工厂Log/LogFactory->命令装载机CommandLoaders->接收过滤器工厂ReceiveFilterFactory->连接过滤Connection Filters。
  3. Socket 服务:多客户端监听,TCP1 、TCP2、。。。。UDP。

SuperSocket 介绍

4、SuperSocket内置的常用协议实现模版

为了减少码农的工作量,SuperSocket内置的常用协议实现模版如下:

  • TerminatorReceiveFilter ,结束符协议(SuperSocket.SocketBase.Protocol.TerminatorReceiveFilter, SuperSocket.SocketBase)
  • 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)

以上模板的使用可参考官方文档http://docs.supersocket.net/v1-6/zh-CN/The-Built-in-Common-Format-Protocol-Implementation-Templates

5、通过请求处理模型可以总结基本的开发流程

  1. 实例化AppServer对象,时刻监听客户端的会话。
  2. 定义RequestInfo实体类型,接收和处理二进制字符流。
  3. 定义数据接收过滤器,ReceiveFilter,接收过滤后的数据,并将数据赋值给RequestInfo实体类型。
  4. 在appServer的构造函数中继承使用接收过滤工厂RequestFilterFactory,并执行自定的ReceiveFilter和RequestInfo。
  5. 在1的数据请求委托事件中解析并使用RequestInfo实体中对应的数据。

二、通过FixedHeaderReceiveFilter解析自定义协议

自定义自己服务器中相关的类,建议类的建立顺序:RequestInfo>ReceiveFilter>AppSession>AppServer

通信协议格式如下:

SuperSocket 介绍

在FixedHeaderReceiveFilter,头部指数据内容之前的数据(即数据长度L之前的部分),以上协议可以知道,头部包含11个字节.

1、自定义请求类型RequestInfo

先实现一个客户端请求的实体类RequestInfo,该RequestInfo类必须实现接口 IRequestInfo,该接口只有一个名为"Key"的字符串类型的属性。
SuperSocket设计了两个RequestInfo类:StringRequestInfo 和BinaryRequestInfo,这里我们自定义一个来GDProtocolRequestInfo实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase.Protocol; namespace GDServer
{ public class GDProtocolRequestInfo : IRequestInfo
{
/// <summary>
/// [不使用]
/// </summary>
public string Key { get; set; } /// <summary>
/// 设备逻辑地址
/// </summary>
public string DeviceLogicalCode { get; set; } /// <summary>
/// 命令序列号
/// </summary>
public string Seq { get; set; } /// <summary>
/// 控制码
/// </summary>
public string ControlCode { get; set; } /// <summary>
/// 数据长度
/// </summary>
public string Length { get; set; } /// <summary>
/// 数据域
/// </summary>
public string Data { get; set; } /// <summary>
/// CS校验
/// </summary>
public string Cs { get; set; } /// <summary>
/// 当前完整帧
/// </summary>
//public string EntireFrame { get; set; }
}
}

2、自定义接收过滤器ReceiveFilter

设计基于类FixedHeaderReceiveFilter实现自己的接收过滤器GDProtocolReceiveFilterV2,主要实现GetBodyLengthFromHeader和ResolveRequestInfo方法,实现如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase.Protocol;
using SuperSocket.Facility.Protocol;//
using SuperSocket.Common;// namespace GDServer
{
/// <summary>
/// 广东规约过滤器V2,(帧格式为GDProtocolRequestInfo)
/// </summary>
public class GDProtocolReceiveFilterV2 : FixedHeaderReceiveFilter<GDProtocolRequestInfo>
{
public GDProtocolReceiveFilterV2()
: base()
{ } /// <summary>
/// 获取数据域和结尾字节长度
/// </summary>
/// <param name="header"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
{
//length为头部(包含两字节的length)长度 //获取高位
byte high = header[offset + length - ];
//获取低位
byte low = header[offset + length - ];
int len = (int)high * + low;
return len + ;//结尾有2个字节
} /// <summary>
/// 实现帧内容解析
/// </summary>
/// <param name="header"></param>
/// <param name="bodyBuffer"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
protected override GDProtocolRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
{
GDProtocolRequestInfo res = new GDProtocolRequestInfo();
string entireFrame = BytesToHexStr(header.Array) + BytesToHexStr(bodyBuffer.CloneRange(offset, length));
//res.EntireFrame = entireFrame;
res.DeviceLogicalCode = entireFrame.Substring(, );
res.Seq = entireFrame.Substring(, );
res.ControlCode = entireFrame.Substring(, );
res.Length = entireFrame.Substring(, );
int dataLen = int.Parse(HEXtoDEC(ReverseHexString(res.Length)));
res.Data = entireFrame.Substring(, dataLen * );
res.Cs = entireFrame.Substring( + dataLen * , );
return res;
} /// <summary>
/// 高低对调
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
string ReverseHexString(string str)
{
char[] buff = new char[str.Length];
for (int i = ; i < str.Length; i += )
{
buff[i] = str[str.Length - i - ];
buff[i + ] = str[str.Length - - i];
}
string s = new string(buff);
return s;
} /// <summary>
/// 16进制转10进制
/// </summary>
/// <param name="HEX"></param>
/// <returns></returns>
string HEXtoDEC(string HEX)
{
return Convert.ToInt64(HEX, ).ToString();
} /// <summary>
/// 转化bytes成16进制的字符
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
string BytesToHexStr(byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = ; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");
}
}
return returnStr;
}
}
}

3、自定义的AppSession

先创建新的AppSession,GDProtocolSessionV2,新的AppServer将使用它。

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using System; namespace GDServer
{
public class GDProtocolSessionV2 : AppSession<GDProtocolSessionV2, GDProtocolRequestInfo>
{
protected override void HandleException(Exception e)
{ }
}
}

4、自定义AppServer

使用该协议的方法是使用接收或者自己定义的接收过滤器工厂来在 SuperSocket 中启用该协议

using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol; namespace GDServer
{
public class GDProtocolServerV2 : AppServer<GDProtocolSessionV2, GDProtocolRequestInfo>
{
public GDProtocolServerV2()
: base(new DefaultReceiveFilterFactory<GDProtocolReceiveFilterV2, GDProtocolRequestInfo>()) //使用默认的接受过滤器工厂 (DefaultReceiveFilterFactory)
{
}
}
}

5、测试程序

这样,GDProtocolServerV2就完成了,下面是测试代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GDServer;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Red;
var gdServer = new GDProtocolServerV2();
gdServer.Setup();
gdServer.NewSessionConnected += gdServer_NewSessionConnected;
gdServer.NewRequestReceived += gdServer_NewRequestReceived;
gdServer.SessionClosed += gdServer_SessionClosed;
gdServer.Start();
Console.WriteLine("server is:" + gdServer.State.ToString());
while (true)
{
if (Console.ReadKey().KeyChar == 'q')
{
gdServer.Stop();
gdServer.Dispose();
return;
}
}
} static void gdServer_SessionClosed(GDProtocolSessionV2 session, SuperSocket.SocketBase.CloseReason value)
{
Console.WriteLine(session.RemoteEndPoint.ToString() + " closed. reason:" + value);
} static void gdServer_NewRequestReceived(GDProtocolSessionV2 session, GDProtocolRequestInfo requestInfo)
{
var info = requestInfo;
Console.WriteLine("receive from: " + session.RemoteEndPoint.ToString());
Console.WriteLine("DeviceLogicalCode:" + info.DeviceLogicalCode);
Console.WriteLine("Seq:" + info.Seq);
Console.WriteLine("ControlCode:" + info.ControlCode);
Console.WriteLine("Length:" + info.Length);
Console.WriteLine("Data:" + info.Data);
Console.WriteLine("Cs:" + info.Cs);
Console.WriteLine("-------------------------------------------------------------");
} static void gdServer_NewSessionConnected(GDProtocolSessionV2 session)
{
Console.WriteLine(session.RemoteEndPoint.ToString() + " connected.");
}
}
}

测试结果:

分别发送符合该协议格式的帧(用TCP调试助手使用hex方式发送)

68 77 77 12 34 00 01 68 A1 03 00 11 11 11 DC 16

68 77 77 12 34 41 01 68 01 0C 00 01 00 00 00 00 00 00 00 30 80 10 80 94 16

68 77 77 12 34 41 01 68 88 08 00 00 00 30 80 00 10 80 00 16 16

68 77 77 12 34 41 01 68 95 23 00 00 0B 00 00 10 00 00 00 00 00 FF FF FF FF FF FF FF FF 00 00 5B 00 00 00 00 00 00 00 00 00 00 00 00 00 32 9E 16

打印结果如下:

server is:Running
127.0.0.1:34360 connected.
receive from: 127.0.0.1:34360
DeviceLogicalCode:77771234
Seq:0001
ControlCode:A1
Length:0300
Data:111111
Cs:DC
-------------------------------------------------------------
receive from: 127.0.0.1:34360
DeviceLogicalCode:77771234
Seq:4101
ControlCode:01
Length:0C00
Data:010000000000000030801080
Cs:94
-------------------------------------------------------------
receive from: 127.0.0.1:34360
DeviceLogicalCode:77771234
Seq:4101
ControlCode:88
Length:0800
Data:0000308000108000
Cs:16
-------------------------------------------------------------
receive from: 127.0.0.1:34360
DeviceLogicalCode:77771234
Seq:4101
ControlCode:95
Length:2300
Data:000B0000100000000000FFFFFFFFFFFFFFFF00005B0000000000000000000000000032
Cs:9E
-------------------------------------------------------------

以上代码请自行引入SuperSocket的dll和System.configuration.dll

本文由http://www.cnblogs.com/xiepeixing/原创,转载请著名出处

三 、SuperSocket 1.6 中文文档

http://docs.supersocket.net/v1-6/zh-CN

四、入门教程

https://www.cnblogs.com/fly-bird/category/938912.html

五、入门实例下载

链接:https://pan.baidu.com/s/1-Q0a4wsNcwyJI7_D0sbsXw 密码:zda7

SuperSocket 介绍的更多相关文章

  1. C&num;网络编程技术SuperSocket实战项目演练

    一.SuperSocket课程介绍 1.1.本期<C#网络编程技术SuperSocket实战项目演练>课程阿笨给大家带来三个基于SuperSocket通讯组件的实战项目演示实例: ● 基于 ...

  2. SuperSocket&period;ClientEngine介绍

    项目地址:https://github.com/kerryjiang/SuperSocket.ClientEngine 其中需要引入的SuperSocket.ProtoBase项目:SuperSock ...

  3. 基于SuperSocket的IIS主动推送消息给android客户端

    在上一篇文章<基于mina框架的GPS设备与服务器之间的交互>中,提到之前一直使用superwebsocket框架做为IIS和APP通信的媒介,经常出现无法通信的问题,必须一天几次的手动回 ...

  4. 开源项目SuperSocket的学习笔记

    近几日想在一个项目中引进一个Socket Server,用来接收客户端发送的命令消息并根据具体的业务逻辑对消息进行处理,然后转发给其它在线的客户端.因为以前在博客园关注过江大渔开源的SuperSock ...

  5. SuperSocket与Netty之实现protobuf协议,包括服务端和客户端

    今天准备给大家介绍一个c#服务器框架(SuperSocket)和一个c#客户端框架(SuperSocket.ClientEngine).这两个框架的作者是园区里面的江大渔. 首先感谢他的无私开源贡献. ...

  6. SuperSocket源码解析之启动过程

    一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...

  7. SuperSocket源码解析之开篇

    一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...

  8. SuperSocket源码解析之开篇 &lpar;转&rpar;

    一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...

  9. 初识SuperSocket

    有一些企业由于以前使用的操作系统是被淘汰的操作系统,例如OpenVMS.现需要将针对openvms开发的通讯程序进行移植到现在的windows操作系统上,通过一段时间的了解,现在需要花时间去找商业性的 ...

随机推荐

  1. C&num; ListView点击列头进行排序

    /// <summary> /// This class is an implementation of the 'IComparer' interface. /// </summa ...

  2. ArcGIS Engine开发之地图基本操作(4)

    ArcGIS Engine开发中数据库的加载 1.加载个人地理数据库数据 个人地理数据库(Personal Geodatabase)使用Miscrosoft Access文件(*.mdb)进行空间数据 ...

  3. 0040 Java学习笔记-多线程-线程run&lpar;&rpar;方法中的异常

    run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ...

  4. CSS基础知识汇总

    前言 原文连接:http://www.cnblogs.com/wanghzh/p/5805678.html 在此基础上又做了大量的扩充 CSS简介 CSS是Cascading Style Sheets ...

  5. T-SQL---多值模糊查询的处理

    多值模糊查询的处理 所谓多值模糊查询,就是应用程序中传递过来多个参数,对这些参数做拆分,拆分之后,对拆分结果的key值分别做模糊查询处理 对于精确匹配时,不管是单个Key值还是多个Key值,都很容易处 ...

  6. Linux和Windows下查看、设置环境变量的比较

    [一]查看环境变量: 1.windows 查看所有的变量:set    范例:>set    查看某个变量的值:set 环境变量名    范例:     >set JAVA_HOME    ...

  7. Swift:函数和闭包

    函数 函数是一个完成独立任务的代码块,Swift中的函数不仅可以像C语言中的函数一样有函数的参数和返回值,而且还支持嵌套,并且有函数参数默认值.可变参数等. //定义一个函数,注意参数和返回值,如果没 ...

  8. android按钮监听器的四种技术

    android开发中经常会用到各种各样的监听器,android监听器的写法与java又有不同的地方; 1,activity中使用内部类实现接口 ,创建内部类实例  使用add方法  与java类似 创 ...

  9. c&num;事件求解

    闲来无聊对于clr一书又重新温习了下,但是看到事件这张后还是有很多的困惑,对于事件能力CLR是这样描述,通知其它对象发生特定的事情. 1.其它对象:是指对于事件的关注者 2.特定的事件:对于满足事件交 ...

  10. 神经网络 Neuroph - Java Neural Network Platform Neuroph

    http://neuroph.sourceforge.net/image_recognition.html https://github.com/neuroph/neuroph