内置的常用协议实现模版

    阅读了前面一篇文档之后, 你可能会觉得用 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)

    与命令行协议类似,一些协议用结束符来确定一个请求.

    例如, 一个协议使用两个字符 "##" 作为结束符, 于是你可以使用类 "TerminatorReceiveFilterFactory":

    默认的请求类型是 StringRequestInfo, 你也可以创建自己的请求类型, 不过这样需要你做一点额外的工作:

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

    1. {
    2. //More code
    3. }
    1. public class YourReceiveFilterFactory : IReceiveFilterFactory<YourRequestInfo>
    2. {
    3. //More code
    4. }

    然后在你的 AppServer 中使用这个接收过滤器工厂(ReceiveFilterFactory).

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

    你也可以使用下面的类更深入的定制这种协议:

    1. CountSpliterReceiveFilter<TRequestInfo>
    2. CountSpliterReceiveFilterFactory<TReceiveFilter>
    3. CountSpliterReceiveFilterFactory<TReceiveFilter, TRequestInfo>

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

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

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

    1. class MyReceiveFilter : BeginEndMarkReceiveFilter<StringRequestInfo>
    2. {
    3. //开始和结束标记也可以是两个或两个以上的字节
    4. private readonly static byte[] BeginMark = new byte[] { (byte)'!' };
    5. private readonly static byte[] EndMark = new byte[] { (byte)'$' };
    6. public MyReceiveFilter()
    7. : base(BeginMark, EndMark) //传入开始标记和结束标记
    8. {
    9. }
    10. protected override StringRequestInfo ProcessMatchedRequest(byte[] readBuffer, int offset, int length)
    11. {
    12. //TODO: 通过解析到的数据来构造请求实例,并返回
    13. }
    14. }

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

    1. public class MyAppServer : AppServer
    2. {
    3. {
    4. }
    5. }

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

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

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

    1. class MyReceiveFilter : FixedHeaderReceiveFilter<BinaryRequestInfo>
    2. {
    3. public MyReceiveFilter()
    4. : base(6)
    5. {
    6. }
    7. protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
    8. {
    9. return (int)header[offset + 4] * 256 + (int)header[offset + 5];
    10. }
    11. protected override BinaryRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
    12. {
    13. return new BinaryRequestInfo(Encoding.UTF8.GetString(header.Array, header.Offset, 4), bodyBuffer.CloneRange(offset, length));
    14. }

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

    • 传入父类构造函数的 6 表示头部的长度;
    • 方法"GetBodyLengthFromHeader(…)" 应该根据接收到的头部返回请求体的长度;
    • 方法 ResolveRequestInfo(….)" 应该根据你接收到的请求头部和请求体返回你的请求类型的实例.