飞鸽传书
A Free Enterprise Instant Messenger™

飞鸽的Json数据协议

企业即时通讯软件飞鸽传书,是一款基于TCP/IP协议、基于局域网广播消息模式的通讯软件,适合企业或政府部门局域网内部使用。 飞鸽传书用户可在企业内部或外部通过该软件进行工作上的交流,软件支持消息发送、文件传输、语音对话等。支持统一的用户管理,并且通讯记录可保存于服务器,查询方便。为您提供安全,稳定的即时通讯解决方案。

前面发表过两篇随笔:《飞鸽传书基类及公共类的定义》和《飞鸽传书数据封包和拆包》,介绍了Socket方面的开发。本文继续探讨使用Json格式来作为Socket收发协议方面的技术问题(可以GOOGLE上找到)。

前面说到,收到的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;
        }
    }
 

JsonTools是一个Json的辅助类,负责Json内容的解析的,由于我的项目是采用C#2.0的,因此Json操作采用了Newtonsoft.Json.dll类库,如果是C#3.5的,采用系统内置类库就可以了。

代码:
    /// <summary>
    /// Json处理类
    /// </summary>
    public class JsonTools
    {
        /// <summary>
        /// 从一个对象信息生成Json串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ObjectToJson(object obj)
        {
            return JavaScriptConvert.SerializeObject(obj);
        }

        /// <summary>
        /// 从一个Json串生成对象信息
        /// </summary>
        /// <param name="jsonString"></param>
        /// <param name="objType"></param>
        /// <returns></returns>
        public static object JsonToObject(string jsonString, Type objType)
        {
            return JavaScriptConvert.DeserializeObject(jsonString, objType);
        }

    }
 

这样就可以实现Json格式内容的发送和接受了。



文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
相关日志:
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.