Beetle.SL对象封装协议详解
Beetle.SL给Silverlight提供了WCF以外的基于对象传送的Socket tcp传输功能,虽然提供了对象来描述协议但如果对其协议的封不了解那似乎和其他平台进行网络通过就比较麻烦了。虽然Beetle.SL是以对象的方式来描述协议,但其灵活度非常的高。以常见的头4字节描述消息长度为例,组件可以通过对象对现有这种协议进行描述,并通过组件进行对象信息交互。在这里介绍如何使用头4节字描述长度的分析器来进行协议分析和获取。HeadSizePackage只是一个抽象类,如果需要使用它来进行分析协议必须继承它并现实两个方法.
- protected abstract IMessage ReadMessageByType(BufferReader reader,out object typetag);
- protected abstract void WriteMessageType(IMessage msg, BufferWriter writer);
这两个方法分别是写入消息的时候如何写入消息类型标记和在读取消息的时候如何获取标记并根据标记来创建相关的信息对象.以下是一个简单的以类的类型名称作为一个标记写入和读取
public class HeadSizePackage:Beetle.HeadSizeOfPackage { protected override Beetle.IMessage ReadMessageByType(Beetle.BufferReader reader, out object typetag) { typetag = reader.ReadString(); switch ((string)typetag) { case "User": return new User(); default: return null; } } protected override void WriteMessageType(Beetle.IMessage msg, Beetle.BufferWriter writer) { if (msg is User) { writer.Write(msg.GetType().Name); } else { writer.Write("NULL"); } } }
以上对象标记处理很简单,如果对象是User就写入类型名称,如果没有配匹就写入一个NULL字符,同样读取的时候如果是标记是User则创建一个User对象返回,这样一个简单协议分析器就定义完成;但这里并没有体现出HeadSizePackage是怎样把对象写入数据流或从流中读取信息。下面通过一个简单对象来详细描述这一点.
public class User:Beetle.IMessage { public string Name; public string Email; public void Load(Beetle.BufferReader reader) { Name = reader.ReadString(); Email = reader.ReadString(); } public void Save(Beetle.BufferWriter writer) { writer.Write(Name); writer.Write(Email); } }
这是一个很简单的User信息,分另有两个成员Name和EMail.当Channel通过HeadSizePackage进行数据写入的时候会一个怎样的格式呢。首先我们实例一个对象并设置相关值.
User user = new User(); user.Name = "henry"; user.Email = "henryfan@msn.com";
通过HeadSizePackage处理后得到的byte[]十六进制信息如下:
2900000004000000557365720500000068656E72791000000068656E727966616E406D736E2E636F6D
接下来通过一个详细的图解来描述这个消息的组成结构:
以上只是HeadSizePackage的一种处理情况,协议的制定有很多种方式。有些情况已有的协议已经存在,那不可能修改它来适应现有的。因此HeadSizePackage提供了足够的灵活性能适应这一点。以下是一个以int为消息标记的实现。
public class HeadSizePackage:Beetle.HeadSizeOfPackage { protected override Beetle.IMessage ReadMessageByType(Beetle.BufferReader reader, out object typetag) { typetag = reader.ReadInt32(); switch ((int)typetag) { case 1: return new User(); default: return null; } } protected override void WriteMessageType(Beetle.IMessage msg, Beetle.BufferWriter writer) { if (msg is User) { writer.Write(1); } else { writer.Write(-1); } } }
同样的消息生成的协议内容会是如下:
25000000010000000500000068656E72791000000068656E727966616E406D736E2E636F6D
通过详细图解来描述这个结构:
实际情况比较多,这里只是简单地描述两种情况,通过组件提供BufferWriter和BufferReader方法足够满足实际情况的需要,以上两个对象的方法详解可以查看:Beetle.SL BufferReader,BufferWriter
在新版的Beetle.SL中集成了数值可变长度写入,可以更好节省带宽资源详细看:http://beetlesl.codeplex.com/