2013年3月16日

SuperSocket的研究(7)—— 内置的通用格式协议实现工具

在阅读过前面的文档后,你可能会发现用SuperSocket来实现你自己的协议可能并不那么容易。SuperSocket提供一些通用协议工具来简化这项工作,它能让你更快、更轻松地构建自己的协议。

终止符协议

与命令行协议类似,一些协议使用终止符来界定一个请求。比如,一个协议使用“##”作为终止符,那么你可以使用TerminatorReceiveFilterFactory这个类。
/// <summary>
/// TerminatorProtocolServer
/// 每个请求都以 "##" 结尾
/// ECHO Your message##
/// </summary>
public class TerminatorProtocolServer : AppServer
{
    public TerminatorProtocolServer()
        : base(new TerminatorReceiveFilterFactory("##"))
    {

    }
}
默认使用的RequestInfo是一个StringRequestInfo,你也可以使用自己的RequsetInfo类,但还需要一点工作:
继承TerminatorReceiveFilter来实现自己的ReceiveFilter:
public class YourReceiveFilter : TerminatorReceiveFilter<YourRequestInfo>
{
    //More code
}
实现能够创建自己请求过滤器实例的ReceiveFilterFactory:
public class YourReceiveFilterFactory : IReceiveFilterFactory<YourRequestInfo>
{
    //More code
}
接下来,就可以在你的AppServer中使用这个请求过滤器工厂了。

带分隔符的固定数目分隔部分协议

一些协议定义的请求格式看上去像是“#部分1#部分2#部分3#部分4#部分5#部分6#部分7#”这样。一个请求中有7个部分,并且都被字符“#”隔开、要实现这种协议也是很容易的:
/// <summary>
/// 你的协议格式类似于这样:
/// #part1#part2#part3#part4#part5#part6#part7#
/// </summary>
public class CountSpliterAppServer : AppServer
{
    public CountSpliterAppServer()
        : base(new CountSpliterReceiveFilterFactory((byte)'#', 8)) // 7个部分,但需要8个分隔符
    {

    }
}
你i也可以使用以下的类来更进一步定制你的协议:
CountSpliterReceiveFilter<TRequestInfo>
CountSpliterReceiveFilterFactory<TReceiveFilter>
CountSpliterReceiveFilterFactory<TReceiveFilter, TRequestInfo>

带请求体长度的固定请求头协议

这种协议规定每个请求包含两个部分,第一部分包含一些请求的基本信息(包括第二部分的长度)。我们通常把第一部分称为请求头,把第二部分称为请求体。
举个例子,我们有一个这样的协议:请求头包含6个字节,头4个字节表示请求的名称,后2个字节表示请求提的长度:
/// +-------+---+-------------------------------+
/// | 请求  |长 |                               |
/// | 名称  |   |         请求体                |
/// |  (4)  |度 |                               |
/// |       |(2)|                               |
/// +-------+---+-------------------------------+
用SuperSocket可以轻松地实现这类协议:
class MyReceiveFilter : FixedHeaderReceiveFilter<BinaryRequestInfo>
{
    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<byte> header, byte[] bodyBuffer, int offset, int length)
    {
        return new BinaryRequestInfo(Encoding.UTF8.GetString(header.Array, header.Offset, 4), bodyBuffer.CloneRange(offset, length));
    }
}
你需要继承FixedHeaderReceiveFilter来实现自己的请求过滤器。
  • 传入父类构造方法的数字6表示请求头的大小为6;
  • 你需要覆盖GetBodyLengthFromHeader(...)方法来使之根据接收到的请求头返回请求体长度;
  • 你需要覆盖ResolveRequestInfo(...)方法,使之根据接收到的请求头和请求体来返回RequestInfo实例。
    然后你可以构建一个接收过滤器工厂或者是使用默认的接收过滤器工厂来使用这个接收过滤器。

    没有评论:

    发表评论