一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

跨平臺(tái)網(wǎng)絡(luò)通信(結(jié)構(gòu)體還是流序列?)

 心不留意外塵 2016-05-06

 http://yuanshuilee.blog.163.com/blog/static/21769727520142273283412/ 

2014-03-27  

網(wǎng)絡(luò)通信通常分為基于數(shù)據(jù)結(jié)構(gòu)的和基于流的。HTTP協(xié)議就是后者的一個(gè)例子。

    有時(shí)為了提高程序的處理速度和數(shù)據(jù)處理的方便,會(huì)使用基于數(shù)據(jù)結(jié)構(gòu)的通信(不需要對(duì)流進(jìn)行解析)。但是,當(dāng)需要在多平臺(tái)間進(jìn)行通信時(shí),基于數(shù)據(jù)結(jié)構(gòu)的通信,往往要十分注意以下幾個(gè)方面:

[1] 字節(jié)序

[2] 變量長(zhǎng)度

[3] 內(nèi)存對(duì)齊

    在常見(jiàn)的系統(tǒng)架構(gòu)中(Linux X86,Windows),非單字節(jié)長(zhǎng)度的變量類型,都是低字節(jié)在前,而在某些特定系統(tǒng)中,如Soalris Sparc平臺(tái),高字節(jié)在前。如果在發(fā)送數(shù)據(jù)前不進(jìn)行處理,那么由Linux X86發(fā)向Soalris Sparc平臺(tái)的數(shù)據(jù)值,勢(shì)必會(huì)有極大的偏差,進(jìn)而程序運(yùn)行過(guò)程中無(wú)法出現(xiàn)預(yù)計(jì)的正常結(jié)果,更嚴(yán)重時(shí),會(huì)導(dǎo)致段錯(cuò)誤。

    對(duì)于此種情況,我們往往使用同一的字節(jié)序。在系統(tǒng)中,有ntohXXX(), htonXXX()等函數(shù),負(fù)責(zé)將數(shù)據(jù)在網(wǎng)絡(luò)字節(jié)序和本地字節(jié)序之間轉(zhuǎn)換。雖然每種系統(tǒng)的本地字節(jié)序不同,但是對(duì)于所有系統(tǒng)來(lái)說(shuō),網(wǎng)絡(luò)字節(jié)序是固定的-----高字節(jié)在前。所以,可以以網(wǎng)絡(luò)字節(jié)序?yàn)橥ㄐ诺臉?biāo)準(zhǔn),發(fā)送前,數(shù)據(jù)都轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序。

    轉(zhuǎn)換的過(guò)程,也建議使用ntohXXX(), htonXXX()等標(biāo)準(zhǔn)函數(shù),這樣代碼可以輕松地在各平臺(tái)間進(jìn)行移植(像通信這種很少依賴系統(tǒng)API的代碼,做成通用版本是不錯(cuò)的選擇)。


    變量的長(zhǎng)度,在不同的系統(tǒng)之間會(huì)有差別,如同是Linux2.6.18的平臺(tái),在64位系統(tǒng)中,指針的長(zhǎng)度為8個(gè)字節(jié),而在32位系統(tǒng)中,指針又是4個(gè)字節(jié)的長(zhǎng)度---此處只是舉個(gè)例子,很少有人會(huì)將指針作為數(shù)據(jù)發(fā)送出去。下面是我整理的在64位Linux系統(tǒng)和32位Linux系統(tǒng)中,幾種常見(jiàn)C語(yǔ)言變量的長(zhǎng)度:

                short    int    long    long long    ptr    time_t

32位           2         4       4             8         4        4

64位           2         4       8             8         8        8

    在定義通信用的結(jié)構(gòu)體時(shí),應(yīng)該考慮使用定長(zhǎng)的數(shù)據(jù)類型,如uint32_t,4字節(jié)的固定長(zhǎng)度,并且這屬于標(biāo)準(zhǔn)C庫(kù)(C99),在各系統(tǒng)中都可使用。


    內(nèi)存對(duì)齊的問(wèn)題,也與系統(tǒng)是64位還是32位有關(guān)。如果你手頭有32位和64位系統(tǒng),不妨寫(xiě)個(gè)簡(jiǎn)單的程序測(cè)試一下,你就會(huì)看到同一個(gè)結(jié)構(gòu)體,即便使用了定長(zhǎng)的數(shù)據(jù)類型,在不同系統(tǒng)中的大小是不同的。對(duì)齊往往是以4字節(jié)或8字節(jié)為準(zhǔn)的,只要你寫(xiě)的測(cè)試程序,變量所占空間沒(méi)有對(duì)齊到4或8的倍數(shù)即可,舉個(gè)簡(jiǎn)單的測(cè)試用的結(jié)構(gòu)體的例子吧:

struct student

{

    char name[7];

    uint32_t id;

    char subject[5];

};

    在每個(gè)系統(tǒng)上看下這個(gè)結(jié)構(gòu)體的長(zhǎng)度吧。

    內(nèi)存對(duì)齊,往往是由編譯器來(lái)做的,如果你使用的是gcc,可以在定義變量時(shí),添加__attribute__,來(lái)決定是否使用內(nèi)存對(duì)齊,或是內(nèi)存對(duì)齊到幾個(gè)字節(jié),以上面的結(jié)構(gòu)體為例:

 1)到4字節(jié),同樣可指定對(duì)齊到8字節(jié)。

struct student

{

    char name[7];

    uint32_t id;

    char subject[5];

} __attribute__ ((aligned(4))); 


2)不對(duì)齊,結(jié)構(gòu)體的長(zhǎng)度,就是各個(gè)變量長(zhǎng)度的和

struct student

{

    char name[7];

    uint32_t id;

    char subject[5];

} __attribute__ ((packed));



雖然,網(wǎng)絡(luò)編程里面的數(shù)據(jù)傳送推薦用序列化,但我不用,還是選擇結(jié)構(gòu)體(返璞歸真),有以下幾點(diǎn)理由:

1.跨平臺(tái)問(wèn)題:

序列化確實(shí)可以很好的跨語(yǔ)言平臺(tái),可大多數(shù)網(wǎng)絡(luò)游戲不需要跨語(yǔ)言平臺(tái)


2.別以為有了序列化就不需要結(jié)構(gòu)體

表面上序列化代碼量小,按順序讀和寫(xiě)char int short LPCSTR ... 就好,邏輯對(duì)象寫(xiě)不寫(xiě)都無(wú)所謂,那就是大錯(cuò)而特錯(cuò)了

待序列化的對(duì)象發(fā)送前的結(jié)構(gòu)還是不可省略的,序列化的過(guò)程就是 object->(按一定順序拆分)write->bytes->(按拆分順序組裝)read->object的過(guò)程

其實(shí)object還是不能省略,很多人寫(xiě)網(wǎng)絡(luò)程序不注重邏輯對(duì)象結(jié)構(gòu),收到的一堆bytes按一定順序讀和寫(xiě)就完事了,這樣雖然靈活,但缺乏結(jié)構(gòu),容易造成混亂,調(diào)試起來(lái)是災(zāi)難

所以結(jié)構(gòu)體(或類)還是省略不了的,所以:別以為有了序列化,就不需要結(jié)構(gòu)體了。


3.結(jié)構(gòu)體存在內(nèi)存對(duì)齊和CPU不兼容的問(wèn)題,可以避免

的確結(jié)構(gòu)體是有內(nèi)存對(duì)齊的問(wèn)題,存在兼容性問(wèn)題,我可以選擇pack(1)把內(nèi)存對(duì)齊給關(guān)閉掉,避免兼容性問(wèn)題,既然選擇了iocp就不打算跨平臺(tái)了,可以避免結(jié)構(gòu)體平臺(tái)兼容的問(wèn)題


4.結(jié)構(gòu)體調(diào)試起來(lái)方便很多,減少內(nèi)存拷貝,效率高

不用序列化可write和read的過(guò)程就不需要過(guò)多考慮(少寫(xiě)太多代碼了),read write 就好像現(xiàn)代社會(huì)每個(gè)人每天都要穿衣服和脫衣服一樣,原始社會(huì)需要嗎?其實(shí)人類進(jìn)化到原始裸奔狀態(tài)才是最爽快的:)

但還是要說(shuō)句公道話:有人說(shuō)序列化編碼解碼read write 需要耗費(fèi)資源, 誠(chéng)然這個(gè)過(guò)程基本等于賦值和內(nèi)存拷貝,那點(diǎn)效率損失主要還在內(nèi)存拷貝上,這點(diǎn)效率損失很小,不能作為序列化的缺點(diǎn),當(dāng)然如果涉及到數(shù)據(jù)加密那將是另外一個(gè)話題


5.結(jié)構(gòu)體貌似呆板,發(fā)送數(shù)據(jù)限制多,發(fā)送變長(zhǎng)數(shù)據(jù)就不方便,數(shù)據(jù)組織起來(lái)也不靈活

我想這是很多人拋棄結(jié)構(gòu)體,選擇用序列化方式發(fā)送和接受數(shù)據(jù)的一個(gè)很重要的原因

但:其實(shí)對(duì)于變長(zhǎng)結(jié)構(gòu)(子結(jié)構(gòu)也是變長(zhǎng))的問(wèn)題,用結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的確很麻煩,但并不代表不能實(shí)現(xiàn)

我已經(jīng)實(shí)現(xiàn)了,而且讀和寫(xiě)變長(zhǎng)子結(jié)構(gòu)體嵌套任意多層都不成問(wèn)題,可以存儲(chǔ)復(fù)雜變長(zhǎng)的數(shù)據(jù)結(jié)構(gòu),

數(shù)據(jù)就如同能自動(dòng)序列化一樣方便,這個(gè)應(yīng)該是技術(shù)難點(diǎn),但細(xì)心去做是可以實(shí)現(xiàn)的


6.關(guān)于結(jié)構(gòu)體指針

游戲里面要發(fā)送的數(shù)據(jù)內(nèi)存事先分配好的,不存在指針,深度復(fù)制更不用考慮,所以內(nèi)存拷貝不會(huì)出錯(cuò)

如果用到指針即使用序列化來(lái)實(shí)現(xiàn)也會(huì)面臨同樣的問(wèn)題也占不了多少便宜,由于C++這們語(yǔ)言的特點(diǎn),

不象java那樣有個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn),對(duì)于序列化本身沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),所以可想而知,有人說(shuō):boost有它的序列化的實(shí)現(xiàn)

其實(shí)那個(gè)實(shí)現(xiàn)不見(jiàn)得就合適你自己,如果真要做序列化,編碼和解碼的仿照那個(gè)過(guò)程自己寫(xiě)才最為牢靠,

哪些指針對(duì)應(yīng)的內(nèi)存需要序列化那些不需要序列化,是個(gè)邏輯結(jié)構(gòu),需要自己說(shuō)了算才好(好像扯遠(yuǎn)了點(diǎn))

說(shuō)回游戲數(shù)據(jù),既然不用需要他用到指針,結(jié)構(gòu)體用來(lái)發(fā)送數(shù)據(jù)也沒(méi)問(wèn)題的


7 平臺(tái)擴(kuò)充問(wèn)題

退一萬(wàn)步的說(shuō):換了語(yǔ)言就基本上換了客戶端,客戶端的數(shù)據(jù)組織形式都要重寫(xiě)

實(shí)在不行還可以考慮用xml json 編碼等等一些跨平臺(tái)的解決方案,現(xiàn)在所寫(xiě)的結(jié)構(gòu)體是可以用來(lái)做數(shù)據(jù)接收的,只是發(fā)送的不再是結(jié)構(gòu)體而已


8.綜上所述


如果需要跨語(yǔ)言平臺(tái),不用序列化(二進(jìn)制流或xml, json文本等等)根本無(wú)法實(shí)現(xiàn)


序列化的優(yōu)點(diǎn)還是非常多的.如果主要是跨平臺(tái)和語(yǔ)言自定義讀寫(xiě)規(guī)則,根據(jù)需要讀寫(xiě)對(duì)象的某一部分?jǐn)?shù)據(jù),


空間浪費(fèi)少,不存在內(nèi)存對(duì)齊問(wèn)題等諸多優(yōu)點(diǎn),缺點(diǎn)就是拐彎抹角,代碼量大,調(diào)試不方便


【參考資料】

http://www.cnblogs.com/chenyadong/archive/2011/09/02/2163654.html

http://blog.163.com/liuweiyoung@126/blog/static/1731310452011823113123261/

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲国产另类久久精品| 爱在午夜降临前在线观看| 国内外免费在线激情视频| 日韩美成人免费在线视频| 久久香蕉综合网精品视频| 蜜桃av人妻精品一区二区三区| 久久精品国产熟女精品| 香港国产三级久久精品三级| 免费观看在线午夜视频| 在线免费视频你懂的观看| 91亚洲国产成人久久| 视频一区中文字幕日韩| 精品日韩国产高清毛片| 亚洲精品国产精品日韩| 午夜精品福利视频观看| 免费黄色一区二区三区| 乱女午夜精品一区二区三区| 日韩人妻一区中文字幕| 日韩精品一区二区毛片 | 亚洲中文字幕视频在线播放| 国产精品白丝久久av| 黄片在线免费看日韩欧美| 中文字幕禁断介一区二区| 亚洲中文字幕熟女丝袜久久| 婷婷色国产精品视频一区| 日韩一级欧美一级久久| 国产人妻精品区一区二区三区| 久草精品视频精品视频精品| 大胆裸体写真一区二区| 亚洲精品中文字幕无限乱码| 亚洲av一区二区三区精品| 日本午夜免费观看视频| 久久精品亚洲精品国产欧美| 亚洲少妇人妻一区二区| 中文字幕中文字幕一区二区| 久久亚洲午夜精品毛片| 国产精品第一香蕉视频| 日韩欧美一区二区不卡看片| 日本福利写真在线观看| 国产高清精品福利私拍| 国产又粗又猛又爽色噜噜|