中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

套接字數據包序列化與反序列化方法是什么

發布時間:2021-10-26 10:41:51 來源:億速云 閱讀:151 作者:iii 欄目:編程語言

這篇文章主要介紹“套接字數據包序列化與反序列化方法是什么”,在日常操作中,相信很多人在套接字數據包序列化與反序列化方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”套接字數據包序列化與反序列化方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1.本文背景

經常做C/S,客戶端與服務端通信基本是TCP/UDP通信,套接字用得飛起。

比如我們有一個系統,這個系統又分幾個系統子模塊進程:

  1. C++服務端

  2. Android 客戶端

  3. iOS 客戶端

  4. WPF桌面管理端 ......

幾個模塊之間通過TCP或者UDP通信,數據包解析與組裝是常規操作,我們定義數據包格式如下:

一個數據包包含包頭和包體,定義如下:

包頭

序號字段名數據類型備注
1消息標識int用于標識數據包是否合法
2名稱string當前消息名稱,用于標識數據包類型
3版本號int當前消息版本號,允許程序中消息存在多個版本,用于版本迭代

包含這三個字段:消息標識、名稱、版本號,唯一確定消息對象。

包體

序號字段名數據類型備注
1字段1數據類型字段1
2字段2數據類型字段2

包體直接定義字段信息,就像定義類屬性一樣。

另包頭與包體中數據類型定義如下:

數據包字段類型定義

序號數據類型備注
1int4個字節的整型值
2string組成格式:字符串實際值字節長度(2個字節)+字符串實際值byte
3char單字節值
4列表組成格式:4個字節列表長度+列表實際數據值byte
5字典同上,具體后源碼

其他數據類型類似,復雜數據類型使用4個字節的值字節長度+實際值byte。

給一個測試數據包

序號字段名數據類型備注
1消息標識int取值:0x4A534604
2消息名稱string三國信息,取值:"ThreeCountries"
3版本號int取值:1
4編號int給三國一個編號吧,取值:1
5國名string取值:"蜀國"
6皇帝string取值:"劉備"
7大將個數int5
8大將1編號int取值:1
9大將1名字string取值:"張飛"
10大將1備注string取值:"三板斧"
11大將2編號int取值:2
12大將2名字string取值:"關羽"
13大將2備注string取值:"青龍偃月刀"
14大將3編號int取值:3
15大將3名字string取值:"趙云"
16大將3備注string取值:"很猛的"
17大將4編號int取值:4
18大將4名字string取值:"馬超"
19大將4備注string取值:"強"
20大將5編號int取值:5
21大將5名字string取值:"黃忠"
22大將5備注string取值:"老當益壯"

大致理解下:

  • 前三個字段是包體:用于標識整個數據包,便于包體解析;

  • 后面的包體,簡單說就是三國中的國家信息簡介,前三個字段為三國中的一個國家基本信息:編號、國名、皇帝,后面是該國家大將信息列表,每個大將有編號、名稱、備注等。

定義數據對象

根據數據包定義,我們可以很快定義類進行使用,不管你是C++還是Java。下面是我用C#寫的對應類,用于序列化與反序列化使用:

/// <summary>
/// 三國
/// </summary>
public class ThreeCountries
{
    /// <summary>
    /// 獲取或者設置 ID
    /// </summary>
    public int ID { get; set; }

    /// <summary>
    /// 獲取或者設置 國名
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 獲取或者設置 皇帝
    /// </summary>
    public string Emperor { get; set; }

    /// <summary>
    /// 獲取或者設置 所選課程列表
    /// </summary>
    public List<FamousGeneral> Courses { get; set; }

    public override string ToString()
    {
        return $"三國之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大將";
    }
}

/// <summary>
/// 三國名將
/// </summary>
public class FamousGeneral
{
    /// <summary>
    /// 獲取或者設置 編號
    /// </summary>
    public int ID { get; set; }

    /// <summary>
    /// 獲取或者設置 名字
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 獲取或者設置 描述
    /// </summary>
    public string Memo { get; set; }

    public override string ToString()
    {
        return $"{ID}:{Name}=>{Memo}";
    }
}

對于上面給的數據包你怎么序列化及反序列化?轉換成數據如下,下節接著討論

ThreeCountries shuKingdom = new ThreeCountries
{
    ID = 1,
    Name = "蜀國",
    Emperor = "劉備",
    Courses = new System.Collections.Generic.List<FamousGeneral>
    {
        new FamousGeneral{ ID=1,Name="張飛",Memo="三板斧"},
        new FamousGeneral{ ID=2,Name="關羽",Memo="青龍偃月刀"},
        new FamousGeneral{ ID=3,Name="趙云",Memo="很猛的"},
        new FamousGeneral{ ID=3,Name="馬超",Memo="強"},
        new FamousGeneral{ ID=3,Name="黃忠",Memo="老當益壯"},
    }
};

2. 常規操作

序列化

代碼太繁瑣,我就寫個不正規的偽代碼吧

定義一個byte數組;
一、寫包頭
1、寫入4字節的消息標識:0x4A534604
計算消息對象名稱字符串“ThreeCountries”長度,及轉換字符串為byte數組
2、寫入2字節的bytes數組長度,寫入實際的byte數組值
3、寫入4字節的消息版本號
二、寫包體
4、寫入4字節的大將個數
循環每個大將信息,依次寫入
5、寫入大將1編號
6、寫入大將1名稱
7、寫入大獎1備注
8、寫入大將2編號
9、寫入大將3名稱
10、寫入大獎4備注
...寫吐了,省略號

反序列化

不想寫了,累

常規操作

定義一個序列化接口,每個網絡對象實現其中的序列化與反序列化接口

public interface ISerializeInterface
{
  byte[] Serialize<T>(T t);
  T Deserialize<T>(byte[] arr);
}

public class ThreeCountries : ISerializeInterface
{
  public byte[] Serialize<T>(T t)
  {
    // 將上面的序列化代碼寫在這
  }
  
  T Deserialize<T>(byte[] arr)
  {
    // 將上面的反序列化代碼寫在這,不好意思我沒寫
  }
}

3. 本文操作

寫了半天的Demo,文章可能就寫的有點水了,我估計讀者也不會仔細看代碼,直接去Github check項目去了,哈哈。

我還是簡單說說吧,實現很簡單,定義一些特性,下面紅框里的代碼文件:

套接字數據包序列化與反序列化方法是什么

使用很簡單,在上面的數據類上加上特性,改動不多,看下面代碼:

/// <summary>
/// 三國
/// </summary>
[NetObject(Name = "ThreeCountries", Version = 1)]
public class ThreeCountries
{
    /// <summary>
    /// 獲取或者設置 ID
    /// </summary>
    [NetObjectProperty(ID = 1)]
    public int ID { get; set; }

    /// <summary>
    /// 獲取或者設置 國名
    /// </summary>
    [NetObjectProperty(ID = 2)]
    public string Name { get; set; }

    /// <summary>
    /// 獲取或者設置 皇帝
    /// </summary>
    [NetObjectProperty(ID = 3)]
    public string Emperor { get; set; }

    /// <summary>
    /// 獲取或者設置 所選課程列表
    /// </summary>
    [NetObjectProperty(ID = 4)]
    public List<FamousGeneral> Courses { get; set; }

    public static NetObjectAttribute CurrentObject = null;

    static ThreeCountries()
    {
        CurrentObject = NetObjectSerializeHelper.GetAttribute<ThreeCountries, NetObjectAttribute>(default(ThreeCountries));
    }

    public override string ToString()
    {
        return $"三國之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大將";
    }
}

/// <summary>
/// 三國名將
/// </summary>
public class FamousGeneral
{
    /// <summary>
    /// 獲取或者設置 編號
    /// </summary>
    [NetObjectProperty(ID = 1)]
    public int ID { get; set; }

    /// <summary>
    /// 獲取或者設置 名字
    /// </summary>
    [NetObjectProperty(ID = 2)]
    public string Name { get; set; }

    /// <summary>
    /// 獲取或者設置 描述
    /// </summary>
    [NetObjectProperty(ID = 3)]
    public string Memo { get; set; }

    public override string ToString()
    {
        return $"{ID}:{Name}=>{Memo}";
    }
}

仔細看的話,只在外層類(ThreeCountries)上加了NetObject特性,和屬性上加了NetObjectProperty特性,分別標識消息名稱、版本號及每個屬性的序列化與反序列化順序即可,類中使用的子對象Courses屬性,也只需要加屬性特性即可,如上。

下面添加單元測試,并且測試通過:

套接字數據包序列化與反序列化方法是什么

到此,關于“套接字數據包序列化與反序列化方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

贡山| 凌云县| 黔南| 永仁县| 宁强县| 丰顺县| 东山县| 太谷县| 巫溪县| 文成县| 印江| 保康县| 晋城| 岳西县| 三原县| 卢湾区| 凯里市| 扎兰屯市| 咸丰县| 皋兰县| 明溪县| 开阳县| 清水县| 五家渠市| 海淀区| 密山市| 时尚| 酉阳| 长沙县| 永和县| 佛坪县| 黄梅县| 扶余县| 门源| 石景山区| 铁力市| 个旧市| 晋江市| 荣昌县| 五常市| 阳东县|