虽然,网络编程里面的数据传送推荐用序列化,但我不用,还是选择结构体(返璞归真),有以下几点理由:
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. 平台扩充问题
退一万步的说:换了语言就基本上换了客户端,客户端的数据组织形式都要重写[Page]
实在不行还可以考虑用xml json 编码等等一些跨平台的解决方案,现在所写的结构体是可以用来做数据接收的,只是发送的不再是结构体而已
8.综上所述
如果需要跨语言平台,不用序列化(二进制流或xml, json文本等等)根本无法实现
序列化的优点还是非常多的.如果主要是跨平台和语言自定义读写规则,根据需要读写对象的某一部分数据,
空间浪费少,不存在内存对齐问题等诸多优点,缺点就是拐弯抹角,代码量大,调试不方便
权衡了良久
数据如果能组织的合理,而且没有跨语言平台的要求,用结构体也未尝不可,毕竟数据发送直来直去还是方便些,减少内存拷贝,效率也高了很多
特别是调试起来容易太多了,衡量利弊我还是放弃了序列化,选择了原始的结构体,只是难在数据的组织(好在基本已经克服了)
我知道:序列化很好很强大,很多网络程序高手根本不屑于用结构体,用这个就好象是旁门左道,狗肉上不了大雅之堂一样,狗肉还是很多人喜欢吃的嘛,:)。
我还是返璞归真选择了结构体