雖然,網(wǎng)絡(luò)編程里面的數(shù)據(jù)傳送推薦用序列化,但我不用,還是選擇結(jié)構(gòu)體(返璞歸真),有以下幾點(diǎn)理由:
1.跨平臺(tái)問題:
序列化確實(shí)可以很好的跨語言平臺(tái),可大多數(shù)網(wǎng)絡(luò)游戲不需要跨語言平臺(tái)
2.別以為有了序列化就不需要結(jié)構(gòu)體
表面上序列化代碼量小,按順序讀和寫char int short LPCSTR ... 就好,邏輯對(duì)象寫不寫都無所謂,那就是大錯(cuò)而特錯(cuò)了
待序列化的對(duì)象發(fā)送前的結(jié)構(gòu)還是不可省略的序列化的過程就是 object->(按一定順序拆分)write->bytes->(按拆分順序組裝)read->object的過程
其實(shí)object還是不能省略,很多人寫網(wǎng)絡(luò)程序不注重邏輯對(duì)象結(jié)構(gòu),收到的一堆bytes按一定順序讀和寫就完事了,這樣雖然靈活,但缺乏結(jié)構(gòu),容易造成混亂,調(diào)試起來是災(zāi)難
所以結(jié)構(gòu)體(或類)還是省略不了的,所以:別以為有了序列化,就不需要結(jié)構(gòu)體了。
3.結(jié)構(gòu)體存在內(nèi)存對(duì)齊和CPU不兼容的問題,可以避免
的確結(jié)構(gòu)體是有內(nèi)存對(duì)齊的問題,存在兼容性問題,我可以選擇pack(1)把內(nèi)存對(duì)齊給關(guān)閉掉,避免兼容性問題,既然選擇了iocp就不打算跨平臺(tái)了,可以避免結(jié)構(gòu)體平臺(tái)兼容的問題
4.結(jié)構(gòu)體調(diào)試起來方便很多,減少內(nèi)存拷貝,效率高
不用序列化可write和read的過程就不需要過多考慮(少寫太多代碼了),read write 就好像現(xiàn)代社會(huì)每個(gè)人每天都要穿衣服和脫衣服一樣,原始社會(huì)需要嗎?其實(shí)人類進(jìn)化到原始裸奔狀態(tài)才是最爽快的:)
但還是要說句公道話:有人說序列化編碼解碼read write 需要耗費(fèi)資源, 誠然這個(gè)過程基本等于賦值和內(nèi)存拷貝,那點(diǎn)效率損失主要還在內(nèi)存拷貝上,這點(diǎn)效率損失很小,不能作為序列化的缺點(diǎn),當(dāng)然如果涉及到數(shù)據(jù)加密那將是另外一個(gè)話題
5.結(jié)構(gòu)體貌似呆板,發(fā)送數(shù)據(jù)限制多,發(fā)送變長數(shù)據(jù)就不方便,數(shù)據(jù)組織起來也不靈活
我想這是很多人拋棄結(jié)構(gòu)體,選擇用序列化方式發(fā)送和接受數(shù)據(jù)的一個(gè)很重要的原因
但:其實(shí)對(duì)于變長結(jié)構(gòu)(子結(jié)構(gòu)也是變長)的問題,用結(jié)構(gòu)體來實(shí)現(xiàn)的確很麻煩,但并不代表不能實(shí)現(xiàn)
我已經(jīng)實(shí)現(xiàn)了,而且讀和寫變長子結(jié)構(gòu)體嵌套任意多層都不成問題,可以存儲(chǔ)復(fù)雜變長的數(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ò)
如果用到指針即使用序列化來實(shí)現(xiàn)也會(huì)面臨同樣的問題也占不了多少便宜,由于C++這們語言的特點(diǎn),
不象java那樣有個(gè)標(biāo)準(zhǔn)實(shí)現(xiàn),對(duì)于序列化本身沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),所以可想而知,有人說:boost有它的序列化的實(shí)現(xiàn)
其實(shí)那個(gè)實(shí)現(xiàn)不見得就合適你自己,如果真要做序列化,編碼和解碼的仿照那個(gè)過程自己寫才最為牢靠,
哪些指針對(duì)應(yīng)的內(nèi)存需要序列化那些不需要序列化,是個(gè)邏輯結(jié)構(gòu),需要自己說了算才好(好像扯遠(yuǎn)了點(diǎn))
說回游戲數(shù)據(jù),既然不用需要他用到指針,結(jié)構(gòu)體用來發(fā)送數(shù)據(jù)也沒問題的
7 平臺(tái)擴(kuò)充問題
退一萬步的說:換了語言就基本上換了客戶端,客戶端的數(shù)據(jù)組織形式都要重寫
實(shí)在不行還可以考慮用xml json 編碼等等一些跨平臺(tái)的解決方案,現(xiàn)在所寫的結(jié)構(gòu)體是可以用來做數(shù)據(jù)接收的,只是發(fā)送的不再是結(jié)構(gòu)體而已
8.綜上所述
如果需要跨語言平臺(tái),不用序列化(二進(jìn)制流或xml, json文本等等)根本無法實(shí)現(xiàn)
序列化的優(yōu)點(diǎn)還是非常多的.如果主要是跨平臺(tái)和語言自定義讀寫規(guī)則,根據(jù)需要讀寫對(duì)象的某一部分?jǐn)?shù)據(jù),
空間浪費(fèi)少,不存在內(nèi)存對(duì)齊問題等諸多優(yōu)點(diǎn),缺點(diǎn)就是拐彎抹角,代碼量大,調(diào)試不方便
權(quán)衡了良久
數(shù)據(jù)如果能組織的合理,而且沒有跨語言平臺(tái)的要求,用結(jié)構(gòu)體也未嘗不可,畢竟數(shù)據(jù)發(fā)送直來直去還是方便些,減少內(nèi)存拷貝,效率也高了很多
特別是調(diào)試起來容易太多了,衡量利弊我還是放棄了序列化,選擇了原始的結(jié)構(gòu)體,只是難在數(shù)據(jù)的組織(好在基本已經(jīng)克服了)
我知道:序列化很好很強(qiáng)大,很多網(wǎng)絡(luò)程序高手根本不屑于直接發(fā)一個(gè)邏輯結(jié)構(gòu)體,用這種方式就好象是旁門左道,狗肉上不了大雅之堂一樣,狗肉還是很多人喜歡吃的嘛,:)。
我還是返璞歸真選擇了結(jié)構(gòu)體
一句話:物盡其用,用的恰當(dāng),夠用就好。
如果有什么不對(duì),敬請(qǐng)拍磚,莫要客氣