• Socket开发探秘基于Json格式的数据协议收发


    前面发表过两篇随笔:《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;
            }
        }

    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格式内容的发送和接受了。

     


    使用测试客户端对数据进行测试,并调用ToString()生成接受到的数据内容,查看具体的内容,得到的效果如下所示。

     

    主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
    专注于Winform开发框架/混合式开发框架Web开发框架Bootstrap开发框架微信门户开发框架的研究及应用
      转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com 
        
  • 相关阅读:
    MAUI 通用权限框架(ABP)
    MAUI 入门教程系列(3.多目标平台)
    MAUI 入门教程系列(4.通用主机)
    Swagger 入门教程
    js对比两个文本的差异并高亮显示差异部分
    崩坏3模拟抽卡243亿张补给卡对比精准和扩充池
    银行业务概要相关知识总结
    R720 idRAC 会话数RAC0218:已达到用户会话的最大数,重起idRAC yi
    linux nginx 安装
    异构系统集成架构与流程图
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/1656912.html
Copyright © 2020-2023  润新知