Socket里面的协议解析是Socket通讯程序设计中最复杂的地方,如果你的应用层协议设计或实现不佳,Socket通讯中常见的粘包,分包就难以避免。SuperSocket内置了命令行格式的协议CommandLineProtocol,如果你的用用使用了其它格式的协议,你就必须自行实现自定义协议CustomProtocol。
实现自定义协议
实现自定义协议需要实现ICustomProtocol的Protocol类,和一个实现ICommandReader接口的CommandReader类。
public interface ICustomProtocol<TCommandInfo>
where TCommandInfo : ICommandInfo
{
ICommandReader<TCommandInfo> CreateCommandReader(IAppServer appServer);
}
实现ICustomProtocol需要一个实现ICommandInfo的类TCommandInfo来作为泛型参数,类应包含你的协议中每个命令/包的基本数据结构。实现CreateCommandReader方法只需根据appServer来实例化你的CommandReader, 下面就来讲讲CommandReader。
public interface ICommandReader<TCommandInfo>
where TCommandInfo : ICommandInfo
{
IAppServer AppServer { get; }
TCommandInfo FindCommandInfo(IAppSession session, byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int left);
int LeftBufferSize { get; }
ICommandReader<TCommandInfo> NextCommandReader { get; }
}
上面是你要实现的ICommandReader接口。
IAppServer AppServer { get; } :
返回当前CommandReader运行于的AppServer;
int LeftBufferSize { get; }:
返回当前CommandReader所缓存数据的大小;
ICommandReader<TCommandInfo> NextCommandReader { get; } :
指定下轮数据接收到时所使用的CommandReader实例, 不设则使用当前CommandReader实例;
TCommandInfo FindCommandInfo(IAppSession session, byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int left);
FindCommandInfo方法是CommandReader要实现的核心方法,各个参数的解释如下:
IAppSession session– Socket所属的AppSession
byte[] readBuffer - 接收缓冲区
int offset – 本次接收到的数据在整个接收缓冲区的位移
int length – 本次接收到的数据的长度
bool isReusableBuffer – 表明接收缓冲区是否会在下次接受中被重复利用,如果是,你的代码就不能将readerBuffer这个缓冲区直接用于CommandReader缓存
out int left - 未解析的本次接收数据的长度
返回值TCommandInfo - 返回在缓冲区内找到协议命令数据,如果未找到,返回null。SuperSocket引擎会根据返回值的Key属性来找到相应的命令来执行。如Key为"ECHO", 名为ECHO的命令将会被执行,此CommandInfo将会是这个命令执行的参数。
使用自定义协议
使用自定义协议的方法很简单,只需在你的AppServer里,调用基类构造方法时将CustomProtocol实例传进去:
class CustomProtocolServer : AppServer<CustomProtocolSession, BinaryCommandInfo>
{
public CustomProtocolServer()
: base(new MyCustomProtocol())
{
}
}
注意AppServer所使用的泛型参数TCommandInfo应于CustomProtocol中的泛型参数TCommandInfo相同。
更详细的示例请参考SuperSocket源代码中QuickStart目录中的GPSSocketServer和CustomProtocol项目。