Unity网络开发基础 —— 实践小项目

概述

接Unity网络开发基础

导入基础知识中的代码

需求分析

手动写Handler类

手动书写消息池

using GamePlayer;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 消息池中 主要是用于 注册 ID和消息类型以及消息处理器类型的映射关系
/// 方便我们获取对象 进行反序列化和消息逻辑处理
/// </summary>
public class MsgPool 
{
    //记录消息类型和ID的映射关系
    private Dictionary<int, Type> messages = new Dictionary<int, Type>();
    //记录消息处理器类型和ID的映射关系
    private Dictionary<int, Type> handlers = new Dictionary<int, Type>();

    public MsgPool()
    {
        //在构造函数中进行 注册 注册映射关系
        Register(1001, typeof(PlayerMsg), typeof(PlayerMsgHandler));
        //后面继续添加消息类
    }

    private void Register(int id, Type messageType, Type handlerType)
    {
        messages.Add(id, messageType);
        handlers.Add(id, handlerType);
    }

    /// <summary>
    /// 根据ID 得到一个指定的消息类对象
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public BaseMsg GetMessage(int id)
    {
        if (!messages.ContainsKey(id))
            return null;
        return Activator.CreateInstance(messages[id]) as BaseMsg;
    }

    /// <summary>
    /// 根据ID 得到一个指定的消息处理类对象
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public BaseHandler GetHandler(int id)
    {
        if (!handlers.ContainsKey(id))
            return null;
        return Activator.CreateInstance(handlers[id]) as BaseHandler;
    }

}

工具生成Handler

工具生成消息池

源码

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using UnityEngine;

namespace GamePlayer
{
    public enum E_Player_Type
    {
        Main,
        Other,
    }
    public class PlayerTest : BaseData
    {
        public List<int> list;
        public Dictionary<int, string> dic;
        public int[] arrays;
        public E_Player_Type type;
        public PlayerData player;

        public override int GetByteNum()
        {
            int num = 0;
            num += 4; //list.Count
            for (int i = 0; i < list.Count; i++)
            {
                num += 4;
            }

            num += 4; //dic.Count
            foreach (int key in dic.Keys)
            {
                num += 4;//key所占的字节数
                num += 4;//value 字符串长度 占的字节数
                num += Encoding.UTF8.GetByteCount(dic[key]);
            }

            num += 4; //arrays.Length 数组长度
            for (int i = 0; i < arrays.Length; i++)
            {
                num += 4;
            }

            num += 4; //枚举 用int来存

            num += player.GetByteNum(); //PlayerData

            return num;
        }

        public override int Reading(byte[] bytes, int beginIndex = 0)
        {
            int index = beginIndex;

            //反序列化 list
            list = new List<int>();
            short listCount = ReadShort(bytes, ref index);            
            for (int i = 0; i < listCount; i++)
            {
                list.Add(ReadInt(bytes, ref index));
            }

            //dic
            dic = new Dictionary<int, string>();
            short dicCount = ReadShort(bytes, ref index);            
            for (int i = 0; i < dicCount; i++)
            {
                dic.Add(ReadInt(bytes, ref index), ReadString(bytes, ref index));
            }

            //arrays
            int arrayLength = ReadShort(bytes, ref index);
            arrays = new int[arrayLength];
            for (int i = 0; i < arrayLength; i++)
            {
                arrays[i] = ReadInt(bytes, ref index);
            }

            //枚举
            type = (E_Player_Type)ReadInt(bytes, ref index);

            //自定义类型
            player = ReadData<PlayerData>(bytes, ref index);

            return index - beginIndex;
        }

        public override byte[] Writing()
        {
            //固定内容
            int index = 0;
            byte[] bytes = new byte[GetByteNum()];

            //可变的 是根据成员变量来决定如何拼接的
            //存储 list的长度
            WriteShort(bytes, (short)list.Count, ref index);
            for (int i = 0; i < list.Count; i++)
            {
                WriteInt(bytes, list[i], ref index);
            }

            //存储 dic
            //先长度
            WriteShort(bytes, (short)dic.Count, ref index);
            foreach (int key in dic.Keys)
            {
                WriteInt(bytes, key, ref index);
                WriteString(bytes, dic[key], ref index);
            }

            //存储 数组
            WriteShort(bytes, (short)arrays.Length, ref index);
            for (int i = 0; i < arrays.Length; i++)
            {
                WriteInt(bytes, arrays[i], ref index);
            }

            //存储 枚举 (我们用一个 int 来存储枚举)type 是一个枚举类型
            WriteInt(bytes, Convert.ToInt32(type), ref index);

            //存储 自定义数据结构类
            WriteData(bytes, player, ref index);

            //固定内容
            return bytes;
        }
    }
}

public class GenerateCSharp 
{
    //协议保存路径
    private string SAVE_PATH = Application.dataPath + "/Scripts/Protocol/";

    //生成枚举
    public void GenerateEnum(XmlNodeList nodes)
    {
        //生成枚举脚本的逻辑
        string namespaceStr = "";
        string enumNameStr = "";
        string fieldStr = "";

        foreach (XmlNode enumNode in nodes)
        {
            //获取命名空间配置信息
            namespaceStr = enumNode.Attributes["namespace"].Value;
            //获取枚举名配置信息
            enumNameStr = enumNode.Attributes["name"].Value;

            //获取所有的字段节点 然后进行字符串拼接
            XmlNodeList enumFields = enumNode.SelectNodes("field");
            //清空上一次的数据
            fieldStr = "";
            foreach (XmlNode enumField in enumFields)
            {
                fieldStr += "\t\t" + enumField.Attributes["name"].Value;
                if (enumField.InnerText != "")
                    fieldStr += " = " + enumField.InnerText;
                fieldStr += ",\r\n";
            }
            //对所有可变的内容进行拼接
            string enumStr = $"namespace {namespaceStr}\r\n" + 
                            "{\r\n" + 
                                $"\tpublic enum {enumNameStr}\r\n" +
                                "\t{\r\n" +
                                    $"{fieldStr}" + 
                                "\t}\r\n" + 
                             "}";

            //保存文件的路径
            string path = SAVE_PATH + namespaceStr + "/Enum/";
            //如果不存在该文件夹 则创建
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            //字符串保存 存储为枚举脚本文件
            //参数一:文件名
            //参数二:转换成string 的 数据
            File.WriteAllText(path + enumNameStr + ".cs", enumStr);

        }

        Debug.Log("枚举生成结束");
    }

    //生成数据结构类
    public void GenerateData(XmlNodeList nodes)
    {
        string namespaceStr = "";
        string classNameStr = "";
        string fieldStr = "";
        //将 GetBytesNum方法 写成字符串
        string getByteNumStr = "";
        // 将 Writing方法 写成字符串
        string writingStr = "";
        //将 Reading方法 写成字符串
        string readingStr = "";

        foreach (XmlNode dataNode in nodes)
        {
            //命名空间
            namespaceStr = dataNode.Attributes["namespace"].Value;
            //类名
            classNameStr = dataNode.Attributes["name"].Value;
            //读取所有字段节点
            XmlNodeList fields = dataNode.SelectNodes("field");

            //通过这个方法进行成员变量声明的拼接 返回拼接结果
            fieldStr = GetFieldStr(fields);

            //通过某个方法 对GetBytesNum函数中的字符串内容进行拼接 返回结果
            getByteNumStr = GetGetBytesNumStr(fields);

            //通过某个方法 对Writing函数中的字符串内容进行拼接 返回结果
            writingStr = GetWritingStr(fields);

            //通过某个方法 对Reading函数中的字符串内容进行拼接 返回结果
            readingStr = GetReadingStr(fields);

            string dataStr = "using System.Collections.Generic;\r\n" +
                             "using System.Text;\r\n" +
                             "using System;\r\n\r\n" + 
                              $"namespace {namespaceStr}\r\n" +
                              "{\r\n" +
                                $"\tpublic class {classNameStr} : BaseData\r\n" +
                                "\t{\r\n" +
                                    $"{fieldStr}\r\n" + 
                                    "\t\tpublic override int GetByteNum()\r\n" + 
                                    "\t\t{\r\n" + 
                                        "\t\t\tint num = 0;\r\n" + 
                                        $"{getByteNumStr}" + 
                                        "\t\t\treturn num;\r\n" + 
                                    "\t\t}\r\n\r\n" + 
                                    "\t\tpublic override byte[] Writing()\r\n" + 
                                    "\t\t{\r\n" + 
                                        "\t\t\tint index = 0;\r\n" + 
                                        "\t\t\tbyte[] bytes = new byte[GetByteNum()];\r\n" + 
                                        $"{writingStr}" + 
                                        "\t\t\treturn bytes;\r\n" + 
                                    "\t\t}\r\n\r\n" +
                                    "\t\tpublic override int Reading(byte[] bytes, int beginIndex = 0)\r\n" +
                                    "\t\t{\r\n" +
                                        "\t\t\tint index = beginIndex;\r\n" +                                        
                                        $"{readingStr}" +
                                        "\t\t\treturn index - beginIndex;\r\n" +
                                    "\t\t}\r\n\r\n" +
                                "\t}\r\n" +
                              "}";

            //保存为 脚本对象
            //保存文件的路径
            string path = SAVE_PATH + namespaceStr + "/Data/";
            //如果没有该路径 就创建
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            //字符串保存 存储为数据结构类脚本
            File.WriteAllText(path + classNameStr + ".cs", dataStr);

        }

        Debug.Log("数据结构类生成结束");
    }


    //生成消息类
    public void CenerateMsg(XmlNodeList nodes)
    {
        string namespaceStr = "";
        string classNameStr = "";
        string idStr = "";
        string fieldStr = "";
        //将 GetBytesNum方法 写成字符串
        string getByteNumStr = "";
        // 将 Writing方法 写成字符串
        string writingStr = "";
        //将 Reading方法 写成字符串
        string readingStr = "";

        foreach (XmlNode dataNode in nodes)
        {
            //命名空间
            namespaceStr = dataNode.Attributes["namespace"].Value;
            //类名
            classNameStr = dataNode.Attributes["name"].Value;
            //消息id
            idStr = dataNode.Attributes["id"].Value;
            //读取所有字段节点
            XmlNodeList fields = dataNode.SelectNodes("field");

            //通过这个方法进行成员变量声明的拼接 返回拼接结果
            fieldStr = GetFieldStr(fields);

            //通过某个方法 对GetBytesNum函数中的字符串内容进行拼接 返回结果
            getByteNumStr = GetGetBytesNumStr(fields);

            //通过某个方法 对Writing函数中的字符串内容进行拼接 返回结果
            writingStr = GetWritingStr(fields);

            //通过某个方法 对Reading函数中的字符串内容进行拼接 返回结果
            readingStr = GetReadingStr(fields);

            string dataStr = "using System.Collections.Generic;\r\n" +
                             "using System.Text;\r\n" +
                             "using System;\r\n\r\n" +
                              $"namespace {namespaceStr}\r\n" +
                              "{\r\n" +
                                $"\tpublic class {classNameStr} : BaseMsg\r\n" +
                                "\t{\r\n" +
                                    $"{fieldStr}\r\n" +
                                    "\t\tpublic override int GetByteNum()\r\n" +
                                    "\t\t{\r\n" +
                                        "\t\t\tint num = 8;\r\n" + //这个8代表的是 消息ID的4个字节 + 消息体长度的4个字节
                                        $"{getByteNumStr}" +
                                        "\t\t\treturn num;\r\n" +
                                    "\t\t}\r\n\r\n" +
                                    "\t\tpublic override byte[] Writing()\r\n" +
                                    "\t\t{\r\n" +
                                        "\t\t\tint index = 0;\r\n" +
                                        "\t\t\tbyte[] bytes = new byte[GetByteNum()];\r\n" +
                                        "\t\t\tWriteInt(bytes, GetID(), ref index);\r\n" + 
                                        "\t\t\tWriteInt(bytes, bytes.Length - 8, ref index);\r\n" + 
                                        $"{writingStr}" +
                                        "\t\t\treturn bytes;\r\n" +
                                    "\t\t}\r\n\r\n" +
                                    "\t\tpublic override int Reading(byte[] bytes, int beginIndex = 0)\r\n" +
                                    "\t\t{\r\n" +
                                        "\t\t\tint index = beginIndex;\r\n" +
                                        $"{readingStr}" +
                                        "\t\t\treturn index - beginIndex;\r\n" +
                                    "\t\t}\r\n\r\n" +
                                    "\t\tpublic override int GetID()\r\n" +
                                    "\t\t{\r\n" +
                                        "\t\t\treturn " + idStr + ";\r\n" +
                                    "\t\t}\r\n\r\n" +
                                "\t}\r\n" +
                              "}";

            //保存为 脚本对象
            //保存文件的路径
            string path = SAVE_PATH + namespaceStr + "/Msg/";
            //如果没有该路径 就创建
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            //字符串保存 存储为数据结构类脚本
            File.WriteAllText(path + classNameStr + ".cs", dataStr);

            //生成处理器脚本
            //判断消息处理器脚本是否存在 如果存在 就不要覆盖了 避免把写过的逻辑处理代码覆盖了
            //如果想要改变 那就直接把没用的删了 它就会自动生成
            if (File.Exists(path + classNameStr + "Handler.cs"))
                continue;

            string handlerStr = $"namespace {namespaceStr}\r\n" +
                                "{\r\n" +
                                    $"\tpublic class {classNameStr}Handler : BaseHandler\r\n" + 
                                    "\t{\r\n" + 
                                        "\t\tpublic override void MsgHandle()\r\n" +
                                        "\t\t{\r\n" + 
                                            $"\t\t\t{classNameStr} msg = message as {classNameStr};\r\n" + 
                                        "\t\t}\r\n" + 
                                    "\t}\r\n" + 
                                "}\r\n";

            //把消息处理器类的内容保存到本地
            File.WriteAllText(path + classNameStr + "Handler.cs", handlerStr);

        }

        Debug.Log("消息类生成结束");
    }

    //生成消息池 主要就是ID和消息类型以及消息处理器类型的对应关系
    public void GenerateMsgPool(XmlNodeList nodes)
    {
        List<string> ids = new List<string>();
        List<string> names = new List<string>();
        List<string> nameSpaces = new List<string>();

        foreach (XmlNode dataNode in nodes)
        {
            //记录所有消息的ID
            string id = dataNode.Attributes["id"].Value;
            if (!ids.Contains(id))
                ids.Add(id);
            else
                Debug.LogError("存在相同ID的消息" + id);

            //记录所有消息的名字
            string name = dataNode.Attributes["name"].Value;
            if (!names.Contains(name))
                names.Add(name);
            else
                Debug.LogError("存在相同名字的消息" + id + ",建议即使在不同命名空间中也不要要同名的信息");

            //获取所有消息的命名空间
            string msgNamespace = dataNode.Attributes["namespace"].Value;
            if (!nameSpaces.Contains(msgNamespace))
                nameSpaces.Add(msgNamespace);

            //获取所有消息注册相关的内容
            string registerStr = "";
            for (int i = 0; i < ids.Count; i++)
            {
                registerStr += $"\t\tRegister({ids[i]}, typeof({names[i]}), typeof({names[i]}Handler));\r\n";
            }

            //获取所有需要引用的命名空间 
            string nameSpaceStr = "";
            for (int i = 0; i < nameSpaces.Count; i++)
            {
                nameSpaceStr += $"using {nameSpaces[i]};\r\n";
            }

            //消息池对应的类的字符串信息
            string msgPoolStr = "using System;\r\n" +
                                "using System.Collections.Generic;\r\n" +
                                nameSpaceStr +
                                "public class MsgPool\r\n" +
                                "{\r\n" +
                                    "\tprivate Dictionary<int, Type> messages = new Dictionary<int, Type>();\r\n" +
                                    "\tprivate Dictionary<int, Type> handlers = new Dictionary<int, Type>();\r\n\r\n" +
                                    "\tpublic MsgPool()\r\n" +
                                    "\t{\r\n" +
                                        registerStr +
                                    "\t}\r\n" +
                                    "\tpublic void Register(int id, Type messageType, Type handlerType)\r\n" +
                                    "\t{\r\n" +
                                        "\t\tmessages.Add(id, messageType);\r\n" +
                                        "\t\thandlers.Add(id, handlerType);\r\n" +
                                    "\t}\r\n" +
                                    "\tpublic BaseMsg GetMessage(int id)\r\n" +
                                    "\t{\r\n" +
                                        "\t\tif (!messages.ContainsKey(id))\r\n" +
                                            "\t\t\treturn null;\r\n" +
                                        "\t\treturn Activator.CreateInstance(messages[id]) as BaseMsg;\r\n" +
                                    "\t}\r\n" +
                                    "\tpublic BaseHandler GetHandler(int id)\r\n" +
                                    "\t{\r\n" +
                                        "\t\tif (!handlers.ContainsKey(id))\r\n" +
                                            "\t\t\treturn null;\r\n" +
                                        "\t\treturn Activator.CreateInstance(handlers[id]) as BaseHandler;\r\n" +
                                    "\t}\r\n" +
                                "}\r\n";

            //看看有没有这个路径
            string path = SAVE_PATH + "/Pool/";
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            //保存到本地
            File.WriteAllText(path + "MsgPool.cs", msgPoolStr);

            Debug.Log("消息池生成结束");
        }

        

    }

    /// <summary>
    /// 获取成员变量声明内容
    /// </summary>
    /// <param name="fields"></param>
    /// <returns></returns>
    private string GetFieldStr(XmlNodeList fields)
    {
        string fieldStr = "";
        foreach (XmlNode field in fields)
        {
            //变量类型
            string type = field.Attributes["type"].Value;
            //变量名
            string fieldName = field.Attributes["name"].Value;

            if (type == "list")
            {
                string T = field.Attributes["T"].Value;
                fieldStr += "\t\tpublic " + "List<" + T + "> ";
            }
            else if (type == "array")
            {
                string data = field.Attributes["data"].Value;
                fieldStr += "\t\tpublic " + data + "[] ";
            }
            else if(type == "dic")
            {
                string Tkey = field.Attributes["Tkey"].Value;
                string Tvalue = field.Attributes["Tvalue"].Value;
                fieldStr += "\t\tpublic " + "Dictionary<" + Tkey + ", " + Tvalue + "> ";
            }
            else if(type == "enum")
            {
                string data = field.Attributes["data"].Value;
                fieldStr += "\t\tpublic " + data + " ";
            }
            else
            {
                fieldStr += "\t\tpublic " + type + " ";
            }

            fieldStr += fieldName + ";\r\n";

        }
        return fieldStr;
    }

    /// <summary>
    /// 拼接 GetBytesNum函数的方法
    /// </summary>
    /// <param name="fields"></param>
    /// <returns></returns>
    private string GetGetBytesNumStr(XmlNodeList fields)
    {
        string bytesNumStr = "";

        string type = "";
        string name = "";
        foreach (XmlNode field in fields)
        {
            type = field.Attributes["type"].Value;
            name = field.Attributes["name"].Value;
            if (type == "list")
            {
                string T = field.Attributes["T"].Value;
                bytesNumStr += "\t\t\tnum += 2;\r\n"; // 2 是为了节约字节数 用一个short去存储数量信息
                bytesNumStr += "\t\t\tfor(int i = 0; i < " + name + ".Count; i++)\r\n";
                //这里使用的是 name + [i] 目的是获取 list当中的元素传入进行使用
                bytesNumStr += "\t\t\t\tnum += " + GetValueBytesNum(T, name + "[i]") + ";\r\n";
            }
            else if (type == "array")
            {
                string data = field.Attributes["data"].Value;
                bytesNumStr += "\t\t\tnum += 2;\r\n";
                bytesNumStr += "\t\t\tfor(int i = 0; i < " + name + ".Length; i++)\r\n";
                bytesNumStr += "\t\t\t\tnum += " + GetValueBytesNum(data, name + "[i]") + ";\r\n";
            }
            else if (type == "dic")
            {
                string Tkey = field.Attributes["Tkey"].Value;
                string Tvalue = field.Attributes["Tvalue"].Value;
                bytesNumStr += "\t\t\tnum += 2;\r\n";
                bytesNumStr += "\t\t\tforeach(" + Tkey + " key in " + name + ".Keys)\r\n";
                bytesNumStr += "\t\t\t{\r\n";
                bytesNumStr += "\t\t\t\tnum += " + GetValueBytesNum(Tkey, "key") + ";\r\n";
                bytesNumStr += "\t\t\t\tnum += " + GetValueBytesNum(Tvalue, name + "[key]") + ";\r\n";
                bytesNumStr += "\t\t\t}\r\n";
            }
            else
                bytesNumStr += "\t\t\tnum += " + GetValueBytesNum(type, name) + ";\r\n";
        }

        return bytesNumStr;

    }

    //获取指定类型的字节数
    private string GetValueBytesNum(string type, string name)
    {
        //其它类型根据需求添加
        switch (type)
        {
            case "int":
            case "float":
            case "enum":
                return "4";
            case "bool":
            case "byte":
                return "1";
            case "short":
                return "2";
            case "long":
            case "double":
                return "8";
            case "string":
                return "4 + Encoding.UTF8.GetByteCount(" + name + ")";
            default:
                return name + ".GetByteNum()";
        }
    }

    /// <summary>
    /// 拼接 Writing函数的方法
    /// </summary>
    /// <param name="field"></param>
    /// <returns></returns>
    private string GetWritingStr(XmlNodeList fields)
    {
        string writingStr = "";

        string type = "";
        string name = "";
        foreach (XmlNode field in fields)
        {
            type = field.Attributes["type"].Value;
            name = field.Attributes["name"].Value;
            if (type == "list")
            {
                string T = field.Attributes["T"].Value;
                writingStr += "\t\t\tWriteShort(bytes, (short)" + name + ".Count, ref index);\r\n";
                writingStr += "\t\t\tfor(int i = 0; i < " + name + ".Count; i++)\r\n";
                writingStr += "\t\t\t\t" + GetFieldWritingStr(T, name + "[i]") + "\r\n";
            }
            else if(type == "array")
            {
                string data = field.Attributes["data"].Value;
                writingStr += "\t\t\tWriteShort(bytes, (short)" + name + ".Length, ref index);\r\n";
                writingStr += "\t\t\tfor(int i = 0; i < " + name + ".Length; i++)\r\n";
                writingStr += "\t\t\t\t" + GetFieldWritingStr(data, name + "[i]") + "\r\n";
            }
            else if (type == "dic")
            {
                string Tkey = field.Attributes["Tkey"].Value;
                string Tvalue = field.Attributes["Tvalue"].Value;
                writingStr += "\t\t\tWriteShort(bytes, (short)" + name + ".Count, ref index);\r\n";
                writingStr += "\t\t\tforeach(" + Tkey + " key in " + name + ".Keys)\r\n";
                writingStr += "\t\t\t{\r\n";
                writingStr += "\t\t\t\t" + GetFieldWritingStr(Tkey, "key") + "\r\n";
                writingStr += "\t\t\t\t" + GetFieldWritingStr(Tvalue, name + "[key]") + "\r\n";
                writingStr += "\t\t\t}\r\n";

            }
            else
            {
                writingStr += "\t\t\t" + GetFieldWritingStr(type, name) + "\r\n";
            }


        }

        return writingStr;
    }

    private string GetFieldWritingStr(string type, string name)
    {
        switch (type)
        {
            case "byte":
                return "WriteByte(bytes, " + name + ", ref index);";
            case "int":
                return "WriteInt(bytes, " + name + ", ref index);";
            case "short":
                return "WriteShort(bytes, " + name + ", ref index);";
            case "long":
                return "WriteLong(bytes, " + name + ", ref index);";
            case "float":
                return "WriteFloat(bytes, " + name + ", ref index);";
            case "bool":
                return "WriteBool(bytes, " + name + ", ref index);";
            case "string":
                return "WriteString(bytes, " + name + ", ref index);";
            case "enum":
                return "WriteInt(bytes, Convert.ToInt32(" + name + "), ref index);"; 
            default:
                return "WriteData(bytes, " + name + ", ref index);";
        }
    }

    //
    private string GetReadingStr(XmlNodeList fields)
    {
        string readingStr = "";

        string type = "";
        string name = "";

        foreach (XmlNode field in fields)
        {
            type = field.Attributes["type"].Value;
            name = field.Attributes["name"].Value;
            if (type == "list")
            {
                string T = field.Attributes["T"].Value;
                readingStr += "\t\t\t" + name + " = new List<" + T + ">();\r\n";
                readingStr += "\t\t\tshort " + name + "Count = ReadShort(bytes, ref index);\r\n";
                readingStr += "\t\t\tfor(int i = 0; i < " + name + "Count; i++)\r\n";
                readingStr += "\t\t\t\t" + name + ".Add(" + GetFieldReadingStr(T) + ");\r\n";
            }
            else if (type == "array")
            {
                string data = field.Attributes["data"].Value;                
                readingStr += "\t\t\tshort " + name + "Length = ReadShort(bytes, ref index);\r\n";
                readingStr += "\t\t\t" + name + " = new " + data + "[" + name + "Length];\r\n";
                readingStr += "\t\t\tfor(int i = 0; i < " + name + "Length; i++)\r\n";
                readingStr += "\t\t\t\t" + name + "[i] = " + GetFieldReadingStr(data) + ";\r\n";
            }
            else if (type == "dic")
            {
                string Tkey = field.Attributes["Tkey"].Value;
                string Tvalue = field.Attributes["Tvalue"].Value;
                readingStr += "\t\t\t" + name + " = new Dictionary<" + Tkey + ", " + Tvalue + ">();\r\n";
                readingStr += "\t\t\tshort " + name + "Count = ReadShort(bytes, ref index);\r\n";
                readingStr += "\t\t\tfor(int i = 0; i < " + name + "Count; i++)\r\n";
                readingStr += "\t\t\t\t" + name + ".Add(" + GetFieldReadingStr(Tkey)
                    + ", " + GetFieldReadingStr(Tvalue) + ");\r\n";
            }
            else if (type == "enum")
            {
                string data = field.Attributes["data"].Value;
                readingStr += "\t\t\t" + name + " = (" + data + ")ReadInt(bytes, ref index);\r\n"; 
            }
            else
                readingStr += "\t\t\t" + name + " = " + GetFieldReadingStr(type) + ";\r\n";
        }

        return readingStr;
    }

    private string GetFieldReadingStr(string type)
    {
        switch (type)
        {
            case "byte":
                return "ReadByte(bytes, ref index)";
            case "int":
                return "ReadInt(bytes, ref index)";
            case "short":
                return "ReadShort(bytes, ref index)";
            case "long":
                return "ReadLong(bytes, ref index)";
            case "bool":
                return "ReadBool(bytes, ref index)";
            case "float":
                return "ReadFloat(bytes, ref index)";
            case "string":
                return "ReadString(bytes, ref index)";
            default:
                return "ReadData<" + type + ">(bytes, ref index)";
        }
    }

}

断线重连

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/892891.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ps提示不能使用移动工具,因为目标通道被隐藏的解决办法

解决&#xff1a;按F7&#xff0c;或者从窗口把图层打开 按图示找到快速蒙版图层。它可能被隐藏或以特殊图标显示。右键删除或者拖到右下角垃圾桶里

岩石分类检测数据集 4700张 岩石检测 带标注 voc yolo 9类

岩石分类检测数据集 4700张 岩石检测 带标注 voc yolo 9类 岩石分类检测数据集 (Rock Classification and Detection Dataset) 描述: 本数据集旨在支持对不同类型的岩石进行自动分类和检测&#xff0c;特别适用于地质勘探、矿物识别、环境监测等领域。通过使用该数据集训练的模…

智慧云党建”主题网站设计与实现(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

5G NR UE初始接入信令流程

文章目录 5G NR UE初始接入信令流程 5G NR UE初始接入信令流程 用户设备向gNB-DU发送RRCSetupRequest消息。gNB-DU 包含 RRC 消息&#xff0c;如果 UE 被接纳&#xff0c;则在 INITIAL UL RRC MESSAGE TRANSFER 消息中包括为 UE 分配的低层配置&#xff0c;并将其传输到 gNB-CU…

Sounding Reference Signal (SRS)

文章目录 探测参考信号&#xff08;SRS&#xff09;Sounding Reference Signals 探测参考信号的生成基序列 探测参考信号&#xff08;SRS&#xff09; 探测参考信号&#xff08;SRS&#xff09;在上行链路中传输&#xff0c;使网络能够估计不同频率下的信道质量。 Sounding R…

2024双十一值得购买的好物有哪些?看完这五款好物让你不后悔!

随着一年一度的双十一购物狂欢节即将拉开帷幕&#xff0c;作为一名热衷于分享购物心得的博主&#xff0c;我今天特别想在这里为大家详细介绍五款我个人非常期待入手的好物。这些产品都是经过我精心挑选和试用的&#xff0c;我相信它们不仅能够满足我的需求&#xff0c;同样也能…

使用HTML和CSS实现3D波浪动画效果

使用HTML和CSS实现3D波浪动画效果 在本篇博客中&#xff0c;将详细介绍如何使用HTML与CSS创建一个3D波浪动画效果。这个效果不仅能够在网页中创建立体感强的视觉体验&#xff0c;还能够通过悬停和聚焦实现与用户的交互。我们将逐步解析代码中的每个部分&#xff0c;帮助你掌握…

Stm32+Esp8266连接阿里云程序移植教程(MQTT协议)

Stm32Esp8266连接阿里云程序移植教程&#xff08;MQTT协议&#xff09; 一、前期准备二、移植过程三、程序的使用3.1 连接上阿里云3.2 传输用户数据到阿里云3.3 解析从阿里云下发给用户的数据3.4 关于调试接口 一、前期准备 自己要的工程文件移植所需的文件&#xff08;如下图&…

[ACTF2020] 新生赛]Exec1

目录 0x01命令执行 [ACTF2020 新生赛]Exec1 1、解法1 2、解法2 3、总结 3.1php命令注入函数 3.2java命令注入函数 3.3常见管道符 0x02SQL注入 [极客大挑战 2019]EasySQL1 0x01命令执行 [ACTF2020 新生赛]Exec1 1、解法1 ping本地&#xff0c;有回显&#xff0c;TTL…

数据分析Python for Data专业书籍pdf

随着大数据时代的到来&#xff0c;数据分析已成为企业决策、科学研究以及日常生活中不可或缺的一部分。对于想要学习数据分析的人来说&#xff0c;Python 是最理想的编程语言之一。其简洁的语法、强大的库以及丰富的社区支持&#xff0c;使得 Python 成为数据分析的首选工具。本…

隐蔽的并发错误

欢迎关注公众号 【11来了】 &#xff0c;持续 中间件源码、系统设计、面试进阶相关内容 在我后台回复 「资料」 可领取 编程高频电子书&#xff01; 在我后台回复「面试」可领取 30w 字的硬核面试笔记&#xff01; 感谢你的关注&#xff01; 隐蔽的 synchronized 并发错误 在使…

基于SpringBoot+Vue+Uniapp汽车保养系统小程序的设计与实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而…

PROFINET转SSI协议模块快速使用说明

Profinet网关PROFINET转SSI协议 PN4SSI模块快速使用说明 * 应用时PNSSI模块时&#xff0c;拨码全部拨到OFF。 (1) 在博途中新建一个项目&#xff0c;通过“选项”——“管理通用站描述文件”添加模块的GSD文件。 选择GSD文件所在的目录&#xff0c;点击安装&#xff1a; (…

天选销冠徐志胜与森马的跨界营销,你get了吗?

在当今这个信息爆炸的时代&#xff0c;品牌如何在众多竞争者中脱颖而出&#xff0c;成为消费者心中的首选&#xff0c;是一个值得深入探讨的问题。知名脱口秀演员徐志胜携手森马推出《绒毛的歌》广告片&#xff0c;以其独特的幽默风格&#xff0c;试图为冬季羽绒服市场注入一股…

CEEMDAN +组合预测模型(Transformer - BiLSTM + ARIMA)

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较 全是干货 | 数据集、学习资料、建模资源分享&#xff01; EMD、EEMD、FEEMD、CEEMD、CEEMDAN的区别、原理和Python实现&#xff08;一&#xff09;EMD-CSDN博客 EMD、EEM…

解决linux服务器磁盘占满问题(详细,有效,100%解决)

应用场景&#xff1a; 在我们的日常开发中&#xff0c;我们的服务器总是在不知不觉中磁盘莫名奇妙少了很多空间&#xff0c;或者被占满了&#xff0c;如果这时候要想要存储什么文件&#xff0c;突然发现空间不够了。但我们通常也不知道那些文件占用的空间大&#xff0c;这时候…

Linux 内核态,用户态,以及如何从内核态到用户态,交互方式有哪些

一、Linux 内核态&#xff0c;用户态 Linux 内核态&#xff0c;用户态&#xff0c;以及如何从内核态到用户态&#xff0c;我来说下我的理解 很多面试官&#xff0c;面试也是照搬照套&#xff0c;网上找的八股文面试题&#xff0c;面试的人也是背八股文&#xff0c;刚好背到了&…

linux 虚拟环境下源码安装DeepSpeed

第一步&#xff1a;创建虚拟环境&#xff1a; conda create -n deepspeed python3.10 第二步&#xff1a;进入虚拟环境&#xff0c;安装Pytorch 2.3.1 # CUDA 12.1 conda install pytorch2.3.1 torchvision0.18.1 torchaudio2.3.1 pytorch-cuda12.1 -c pytorch -c nvidia 第…

OJ题:随机链表的复制—Java数据结构

目录 随机链表的复制 1. 完整题目 2.错误做法 3.第一次遍历 1.拷贝所有旧节点的val域 2. 串联老节点和新节点 3. 第一次遍历代码&#xff1a; 4.第二次遍历 1. 表示出新链表的节点 2. 表示出新节点的next,random 3. 通过映射关系赋值next,random 4. 第二次遍历代码…

DAY53WEB 攻防-XSS 跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本

知识点&#xff1a; 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-PDF制作&配合上传 4、XSS跨站-SWF制作&反编译&上传 XSS分类&#xff1a;https://www.fooying.com/the-art-of-xss-1-introduction/&#xff08;失效了&#xff09; …