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