您好,登錄后才能下訂單哦!
這篇文章主要介紹“套接字數據包序列化與反序列化方法是什么”,在日常操作中,相信很多人在套接字數據包序列化與反序列化方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”套接字數據包序列化與反序列化方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
經常做C/S,客戶端與服務端通信基本是TCP/UDP通信,套接字用得飛起。
比如我們有一個系統,這個系統又分幾個系統子模塊進程:
C++服務端
Android 客戶端
iOS 客戶端
WPF桌面管理端 ......
幾個模塊之間通過TCP或者UDP通信,數據包解析與組裝是常規操作,我們定義數據包格式如下:
一個數據包包含包頭和包體,定義如下:
序號 | 字段名 | 數據類型 | 備注 |
---|---|---|---|
1 | 消息標識 | int | 用于標識數據包是否合法 |
2 | 名稱 | string | 當前消息名稱,用于標識數據包類型 |
3 | 版本號 | int | 當前消息版本號,允許程序中消息存在多個版本,用于版本迭代 |
包含這三個字段:消息標識、名稱、版本號,唯一確定消息對象。
序號 | 字段名 | 數據類型 | 備注 |
---|---|---|---|
1 | 字段1 | 數據類型 | 字段1 |
2 | 字段2 | 數據類型 | 字段2 |
包體直接定義字段信息,就像定義類屬性一樣。
另包頭與包體中數據類型定義如下:
序號 | 數據類型 | 備注 |
---|---|---|
1 | int | 4個字節的整型值 |
2 | string | 組成格式:字符串實際值字節長度(2個字節)+字符串實際值byte |
3 | char | 單字節值 |
4 | 列表 | 組成格式:4個字節列表長度+列表實際數據值byte |
5 | 字典 | 同上,具體后源碼 |
其他數據類型類似,復雜數據類型使用4個字節的值字節長度+實際值byte。
序號 | 字段名 | 數據類型 | 備注 |
---|---|---|---|
1 | 消息標識 | int | 取值:0x4A534604 |
2 | 消息名稱 | string | 三國信息,取值:"ThreeCountries" |
3 | 版本號 | int | 取值:1 |
4 | 編號 | int | 給三國一個編號吧,取值:1 |
5 | 國名 | string | 取值:"蜀國" |
6 | 皇帝 | string | 取值:"劉備" |
7 | 大將個數 | int | 5 |
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="老當益壯"}, } };
代碼太繁瑣,我就寫個不正規的偽代碼吧
定義一個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) { // 將上面的反序列化代碼寫在這,不好意思我沒寫 } }
寫了半天的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屬性,也只需要加屬性特性即可,如上。
下面添加單元測試,并且測試通過:
到此,關于“套接字數據包序列化與反序列化方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。