您好,登錄后才能下訂單哦!
這篇文章主要介紹“套接字?jǐn)?shù)據(jù)包序列化與反序列化方法是什么”,在日常操作中,相信很多人在套接字?jǐn)?shù)據(jù)包序列化與反序列化方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”套接字?jǐn)?shù)據(jù)包序列化與反序列化方法是什么”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
經(jīng)常做C/S,客戶端與服務(wù)端通信基本是TCP/UDP通信,套接字用得飛起。
比如我們有一個(gè)系統(tǒng),這個(gè)系統(tǒng)又分幾個(gè)系統(tǒng)子模塊進(jìn)程:
C++服務(wù)端
Android 客戶端
iOS 客戶端
WPF桌面管理端 ......
幾個(gè)模塊之間通過TCP或者UDP通信,數(shù)據(jù)包解析與組裝是常規(guī)操作,我們定義數(shù)據(jù)包格式如下:
一個(gè)數(shù)據(jù)包包含包頭和包體,定義如下:
序號(hào) | 字段名 | 數(shù)據(jù)類型 | 備注 |
---|---|---|---|
1 | 消息標(biāo)識(shí) | int | 用于標(biāo)識(shí)數(shù)據(jù)包是否合法 |
2 | 名稱 | string | 當(dāng)前消息名稱,用于標(biāo)識(shí)數(shù)據(jù)包類型 |
3 | 版本號(hào) | int | 當(dāng)前消息版本號(hào),允許程序中消息存在多個(gè)版本,用于版本迭代 |
包含這三個(gè)字段:消息標(biāo)識(shí)、名稱、版本號(hào),唯一確定消息對(duì)象。
序號(hào) | 字段名 | 數(shù)據(jù)類型 | 備注 |
---|---|---|---|
1 | 字段1 | 數(shù)據(jù)類型 | 字段1 |
2 | 字段2 | 數(shù)據(jù)類型 | 字段2 |
包體直接定義字段信息,就像定義類屬性一樣。
另包頭與包體中數(shù)據(jù)類型定義如下:
序號(hào) | 數(shù)據(jù)類型 | 備注 |
---|---|---|
1 | int | 4個(gè)字節(jié)的整型值 |
2 | string | 組成格式:字符串實(shí)際值字節(jié)長(zhǎng)度(2個(gè)字節(jié))+字符串實(shí)際值byte |
3 | char | 單字節(jié)值 |
4 | 列表 | 組成格式:4個(gè)字節(jié)列表長(zhǎng)度+列表實(shí)際數(shù)據(jù)值byte |
5 | 字典 | 同上,具體后源碼 |
其他數(shù)據(jù)類型類似,復(fù)雜數(shù)據(jù)類型使用4個(gè)字節(jié)的值字節(jié)長(zhǎng)度+實(shí)際值byte。
序號(hào) | 字段名 | 數(shù)據(jù)類型 | 備注 |
---|---|---|---|
1 | 消息標(biāo)識(shí) | int | 取值:0x4A534604 |
2 | 消息名稱 | string | 三國(guó)信息,取值:"ThreeCountries" |
3 | 版本號(hào) | int | 取值:1 |
4 | 編號(hào) | int | 給三國(guó)一個(gè)編號(hào)吧,取值:1 |
5 | 國(guó)名 | string | 取值:"蜀國(guó)" |
6 | 皇帝 | string | 取值:"劉備" |
7 | 大將個(gè)數(shù) | int | 5 |
8 | 大將1編號(hào) | int | 取值:1 |
9 | 大將1名字 | string | 取值:"張飛" |
10 | 大將1備注 | string | 取值:"三板斧" |
11 | 大將2編號(hào) | int | 取值:2 |
12 | 大將2名字 | string | 取值:"關(guān)羽" |
13 | 大將2備注 | string | 取值:"青龍偃月刀" |
14 | 大將3編號(hào) | int | 取值:3 |
15 | 大將3名字 | string | 取值:"趙云" |
16 | 大將3備注 | string | 取值:"很猛的" |
17 | 大將4編號(hào) | int | 取值:4 |
18 | 大將4名字 | string | 取值:"馬超" |
19 | 大將4備注 | string | 取值:"強(qiáng)" |
20 | 大將5編號(hào) | int | 取值:5 |
21 | 大將5名字 | string | 取值:"黃忠" |
22 | 大將5備注 | string | 取值:"老當(dāng)益壯" |
大致理解下:
前三個(gè)字段是包體:用于標(biāo)識(shí)整個(gè)數(shù)據(jù)包,便于包體解析;
后面的包體,簡(jiǎn)單說就是三國(guó)中的國(guó)家信息簡(jiǎn)介,前三個(gè)字段為三國(guó)中的一個(gè)國(guó)家基本信息:編號(hào)、國(guó)名、皇帝,后面是該國(guó)家大將信息列表,每個(gè)大將有編號(hào)、名稱、備注等。
根據(jù)數(shù)據(jù)包定義,我們可以很快定義類進(jìn)行使用,不管你是C++還是Java。下面是我用C#寫的對(duì)應(yīng)類,用于序列化與反序列化使用:
/// <summary> /// 三國(guó) /// </summary> public class ThreeCountries { /// <summary> /// 獲取或者設(shè)置 ID /// </summary> public int ID { get; set; } /// <summary> /// 獲取或者設(shè)置 國(guó)名 /// </summary> public string Name { get; set; } /// <summary> /// 獲取或者設(shè)置 皇帝 /// </summary> public string Emperor { get; set; } /// <summary> /// 獲取或者設(shè)置 所選課程列表 /// </summary> public List<FamousGeneral> Courses { get; set; } public override string ToString() { return $"三國(guó)之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大將"; } } /// <summary> /// 三國(guó)名將 /// </summary> public class FamousGeneral { /// <summary> /// 獲取或者設(shè)置 編號(hào) /// </summary> public int ID { get; set; } /// <summary> /// 獲取或者設(shè)置 名字 /// </summary> public string Name { get; set; } /// <summary> /// 獲取或者設(shè)置 描述 /// </summary> public string Memo { get; set; } public override string ToString() { return $"{ID}:{Name}=>{Memo}"; } }
對(duì)于上面給的數(shù)據(jù)包你怎么序列化及反序列化?轉(zhuǎn)換成數(shù)據(jù)如下,下節(jié)接著討論
ThreeCountries shuKingdom = new ThreeCountries { ID = 1, Name = "蜀國(guó)", Emperor = "劉備", Courses = new System.Collections.Generic.List<FamousGeneral> { new FamousGeneral{ ID=1,Name="張飛",Memo="三板斧"}, new FamousGeneral{ ID=2,Name="關(guān)羽",Memo="青龍偃月刀"}, new FamousGeneral{ ID=3,Name="趙云",Memo="很猛的"}, new FamousGeneral{ ID=3,Name="馬超",Memo="強(qiáng)"}, new FamousGeneral{ ID=3,Name="黃忠",Memo="老當(dāng)益壯"}, } };
代碼太繁瑣,我就寫個(gè)不正規(guī)的偽代碼吧
定義一個(gè)byte數(shù)組; 一、寫包頭 1、寫入4字節(jié)的消息標(biāo)識(shí):0x4A534604 計(jì)算消息對(duì)象名稱字符串“ThreeCountries”長(zhǎng)度,及轉(zhuǎn)換字符串為byte數(shù)組 2、寫入2字節(jié)的bytes數(shù)組長(zhǎng)度,寫入實(shí)際的byte數(shù)組值 3、寫入4字節(jié)的消息版本號(hào) 二、寫包體 4、寫入4字節(jié)的大將個(gè)數(shù) 循環(huán)每個(gè)大將信息,依次寫入 5、寫入大將1編號(hào) 6、寫入大將1名稱 7、寫入大獎(jiǎng)1備注 8、寫入大將2編號(hào) 9、寫入大將3名稱 10、寫入大獎(jiǎng)4備注 ...寫吐了,省略號(hào)
不想寫了,累
定義一個(gè)序列化接口,每個(gè)網(wǎng)絡(luò)對(duì)象實(shí)現(xiàn)其中的序列化與反序列化接口
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,文章可能就寫的有點(diǎn)水了,我估計(jì)讀者也不會(huì)仔細(xì)看代碼,直接去Github check項(xiàng)目去了,哈哈。
我還是簡(jiǎn)單說說吧,實(shí)現(xiàn)很簡(jiǎn)單,定義一些特性,下面紅框里的代碼文件:
使用很簡(jiǎn)單,在上面的數(shù)據(jù)類上加上特性,改動(dòng)不多,看下面代碼:
/// <summary> /// 三國(guó) /// </summary> [NetObject(Name = "ThreeCountries", Version = 1)] public class ThreeCountries { /// <summary> /// 獲取或者設(shè)置 ID /// </summary> [NetObjectProperty(ID = 1)] public int ID { get; set; } /// <summary> /// 獲取或者設(shè)置 國(guó)名 /// </summary> [NetObjectProperty(ID = 2)] public string Name { get; set; } /// <summary> /// 獲取或者設(shè)置 皇帝 /// </summary> [NetObjectProperty(ID = 3)] public string Emperor { get; set; } /// <summary> /// 獲取或者設(shè)置 所選課程列表 /// </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 $"三國(guó)之一{ID}:{Name}皇帝{Emperor},有 {Courses.Count}名大將"; } } /// <summary> /// 三國(guó)名將 /// </summary> public class FamousGeneral { /// <summary> /// 獲取或者設(shè)置 編號(hào) /// </summary> [NetObjectProperty(ID = 1)] public int ID { get; set; } /// <summary> /// 獲取或者設(shè)置 名字 /// </summary> [NetObjectProperty(ID = 2)] public string Name { get; set; } /// <summary> /// 獲取或者設(shè)置 描述 /// </summary> [NetObjectProperty(ID = 3)] public string Memo { get; set; } public override string ToString() { return $"{ID}:{Name}=>{Memo}"; } }
仔細(xì)看的話,只在外層類(ThreeCountries)上加了NetObject特性,和屬性上加了NetObjectProperty特性,分別標(biāo)識(shí)消息名稱、版本號(hào)及每個(gè)屬性的序列化與反序列化順序即可,類中使用的子對(duì)象Courses屬性,也只需要加屬性特性即可,如上。
下面添加單元測(cè)試,并且測(cè)試通過:
到此,關(guān)于“套接字?jǐn)?shù)據(jù)包序列化與反序列化方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。