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