首页 / 软件开发 / .NET编程技术 / Socket开发探秘--基于Json格式的数据协议收发
Socket开发探秘--基于Json格式的数据协议收发2011-04-12 博客园 伍华聪前面发表过两篇随笔:《Socket开发探秘--基类及公共类的定义》和《Socket开发探秘-- 数据封包和拆包》,介绍了Socket方面的开发。本文继续探讨使用Json格式来作为Socket收 发协议方面的技术问题。前面说到,收到的Socket数据经过粗略的解析后,就是PreData类型的数据,这个是通用 的数据格式,我们需要进一步处理才能转化为所能认识的数据对象(实体类对象),同样, 我们发送数据的时候,内容部分肯定是按照一定协议规则串联起来的数据,那么我们就需要 把实体转化为发送的数据格式。综上所述,我们通过实体类,必须实现数据的发送和读取的 转换。 由于数据的封包拆包是一个繁琐的过程,代码重复性比较多,而且也容易出错。前面介绍 过设计一个基类,我们把所有对数据的拆包和封包,利用反射机制,减少我们的代码量,提 高代码的优雅性。 但是后来有人建议,可能使用Json格式的数据内容可能更好,确实,如 果是采用以|分割符号的内容,有一个缺点,就是数据内容比较难懂(有时候我们还是需要分 析数据包的),Json会更易读一些。 另外,使用Json可以脱离字段顺序的关系,可以向后 兼容一些历史的协议,例如首次定义的协议有字段A、B,后来服务器升级,升级增加支持C、 D,旧的客户端可以和新的客户端并存,增加了兼容性。因此我在此基础上优化一下代码,使其支持Json格式的数据发送,其实由于之前的代码封 装的还算比较好,因此修改为Json格式的协议内容,只需要修改BaseEntity中几行代码即可 实现,下面贴出修改代码的前后对比(注释掉的代码是原来的代码):public class BaseEntity
{
protected string HeaderKey;
public BaseEntity()
{
}
/// <summary>
/// 转换Socket接收到的信息为对象信息
/// </summary>
/// <param name="data">Socket接收到的信息 </param>
public BaseEntity(string data)
{
#region 普通按顺序构造的代码
//string[] dataArray = null;
//dataArray = NetStringUtil.UnPack(data);
//if (dataArray != null && dataArray.Length > 0)
//{
// int i = 0;
// FieldInfo[] fieldArray = ReflectionUtil.GetFields(this);
// if (fieldArray == null || dataArray.Length != fieldArray.Length)
// {
// throw new ArgumentException("收到 的信息和字段信息不一致");
// }
// if (fieldArray != null)
// {
// foreach (FieldInfo info in fieldArray)
// {
// string strValue = dataArray[i++];
// ReflectionUtil.SetField (this, info.Name, strValue);
// }
// }
//}
#endregion
//Json格式转换后的内容,肯定是小于或者等于实体类的内容
//因为对象要兼容历史的Json内容,通过反射以最小的成员来 赋值
BaseEntity obj = JsonTools.JsonToObject(data, this.GetType()) as BaseEntity;
if (obj != null)
{
FieldInfo[] fieldArray = ReflectionUtil.GetFields(obj);
foreach (FieldInfo info in fieldArray)
{
object value = ReflectionUtil.GetField(obj, info.Name);
ReflectionUtil.SetField(this, info.Name, value);
}
}
}
/// <summary>
/// 转换对象为Socket发送格式的字符串
/// </summary>
/// <returns></returns>
public override string ToString()
{
string data = "";
#region 普通按顺序构造的代码
//FieldInfo[] fieldArray = ReflectionUtil.GetFields(this);
//StringBuilder sb = new StringBuilder();
//if (fieldArray != null)
//{
// foreach (FieldInfo info in fieldArray)
// {
// sb.Append(ReflectionUtil.GetField (this, info.Name));
// sb.Append("|");
// }
//}
//data = sb.ToString().Trim("|");
#endregion
#region 按Json格式构造的代码
data = JsonTools.ObjectToJson(this);
#endregion
if (string.IsNullOrEmpty(HeaderKey))
{
throw new ArgumentNullException ("DataTypeKey", "实体类未指定协议类型");
}
data = NetStringUtil.PackSend(HeaderKey, data);
return data;
}
}