﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-3d Game Walkman -随笔分类-网络模块</title><link>http://www.cppblog.com/tonykee/category/7260.html</link><description>3d图形渲染，网络引擎 — tonykee's  Blog</description><language>zh-cn</language><lastBuildDate>Sat, 09 May 2009 08:43:35 GMT</lastBuildDate><pubDate>Sat, 09 May 2009 08:43:35 GMT</pubDate><ttl>60</ttl><item><title>游戏资源在线更新的思路</title><link>http://www.cppblog.com/tonykee/archive/2009/05/08/82283.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Fri, 08 May 2009 15:27:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2009/05/08/82283.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/82283.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2009/05/08/82283.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/82283.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/82283.html</trackback:ping><description><![CDATA[
总的来说，和JIT即时编译机制有相通之处，就是一个创建时间的比较
<p>&#160;</p>
<p>首先要明白：客户端的文件如果是最新的，那么创建时间肯定晚于服务器上文件的创建时间，反之客户端的文件就是旧的需要更新了，但是为了提高更新效率，并不是一个个和服务器上的文件做对比</p>
<p>而是建立一个文件列表索引文件，里面记录服务器上的&#8220;最新版&#8221;所有文件的创建时间，首先更新本地的索引文件，如果更新了，说明服务器上的文件列表有更新，然后和本地做对比，整理一份需要更新或新建的文件列表清单，然后主动连接服务器进行下载，全部完成以后，在索引文件进行记录，更新完一个就记录一个ok，这样方便&#8220;断点续传&#8221;，所有都更新完成，全部是ok了，就证明本地都是最新的了，不过这里面有个小问题是值得注意的，本地文件的创建时间不能是本地计算机的时间，应该下载完以后，修改成服务器的当前时间，（比如如果本地时间设置到了一年以前）那本地的列表可能永远都是旧的，每次都要更新，这是可怕的。</p>
<p>通过这个文件列表索引，能大大提高更新效率，而且也能做好版本的控制。</p>
<p>另外，更新服务器一般和游戏服务器分离，大致思路就是这样</p>
<p>打包和网络传输方面，自己封装一套序列化和反序列化的IO流协议就可以了，游戏里面这些都必须是最基本的功能了</p><p>当然，这套思路还有一些不完善的地方，比如更新正在运行的exe或一些内存保护的DLL，是比较麻烦的事情,需要尽量避免</p><img src ="http://www.cppblog.com/tonykee/aggbug/82283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2009-05-08 23:27 <a href="http://www.cppblog.com/tonykee/archive/2009/05/08/82283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>上午写了两个类，实现了自定义资源文件，数据流的存取，一个字爽</title><link>http://www.cppblog.com/tonykee/archive/2008/03/08/43960.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Sat, 08 Mar 2008 07:02:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/03/08/43960.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/43960.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/03/08/43960.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/43960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/43960.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/tonykee/archive/2008/03/08/43960.html'>阅读全文</a><img src ="http://www.cppblog.com/tonykee/aggbug/43960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-03-08 15:02 <a href="http://www.cppblog.com/tonykee/archive/2008/03/08/43960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>这段时间加入了网络序列化的功能</title><link>http://www.cppblog.com/tonykee/archive/2008/03/01/43523.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Sat, 01 Mar 2008 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/03/01/43523.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/43523.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/03/01/43523.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/43523.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/43523.html</trackback:ping><description><![CDATA[<p>前面的文章也提到了，看了一些服务器的大师级的代码，SmartStruct和自定义序列化的方式都有，如果单单只用C结构体作为语意数据载体固然可以，但很多网友也提出了很多质疑，最大的缺陷就是灵活性欠佳，诚然如此。<br><br>这段时间沉下了心，好好写了一些类主要有：</p>
<p>ObjectStream<br>StreamBuffer<br>SerializeMap<br>PacketStruct<br>...<br><br>等等，有了前人的经验，似乎也算比较顺利，一个个从基本的数字，<br>到数组，到char[] (很多资料也称之为：raw 二进制序列)<br>再到STL 的一系列容器的序列化工作都实现了<br><br>其中大量使用了模版类的泛型设计，不必要求一个可序列化的类必须继承某某基类，只需要具备以下：<br><br>&nbsp;SerializeTag ComputeTag();<br>&nbsp;bool Read(ObjectStream&amp; stream);<br>&nbsp;bool Write(ObjectStream&amp; stream);<br>&nbsp;DWORD GetLength(ObjectStream&amp; stream);<br>&nbsp;bool operator==(const PacketHeader &amp;other) const;<br><br>五个方法就可以了，如果随意给你一个事先定义好的类，可以实现序列化吗？当然可以，只需要写出该类的<br>Wrapped Proxy，再添加这5个方法，就能通过 ObjectStream 和 StreamBuffer 实现该类的序列化了<br><br>这些是写完成了，回头看看自己已经写好的网络逻辑模块，犯愁了。<br>唉&#8230;&#8230;，加入序列化，相当于高层次的通讯协议全都变了，包结构要改，所有的业务逻辑通讯代码随之要改。<br><br>之前的工作&#8230;&#8230; 又要写大量的重构代码了。<br><br>重构真是件痛苦的事情。<br>最坏的打算把之前的一些逻辑东西按现有思路重写一遍嘛，二次加工也许能应祸得福，把破旧看不过眼的地方重整理的更漂亮，好比重新装修升级一样<br><br>现在，只能告诉自己一件事，沉下心，沉注气。<br></p>
<img src ="http://www.cppblog.com/tonykee/aggbug/43523.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-03-01 17:15 <a href="http://www.cppblog.com/tonykee/archive/2008/03/01/43523.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>返璞归真，网络传输——结构体还是序列化？</title><link>http://www.cppblog.com/tonykee/archive/2008/02/17/42829.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Sun, 17 Feb 2008 04:53:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/02/17/42829.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/42829.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/02/17/42829.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/42829.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/42829.html</trackback:ping><description><![CDATA[<p>虽然,网络编程里面的数据传送推荐用序列化,但我不用,还是选择结构体(返璞归真),有以下几点理由:<br>1.跨平台问题：<br>&nbsp; 序列化确实可以很好的跨语言平台,可大多数网络游戏不需要跨语言平台</p>
<p>2.别以为有了序列化就不需要结构体<br>&nbsp; 表面上序列化代码量小，按顺序读和写char int short LPCSTR ... 就好，逻辑对象写不写都无所谓，那就是大错而特错了<br>&nbsp; 待序列化的对象发送前的结构还是不可省略的序列化的过程就是 object-&gt;(按一定顺序拆分)write-&gt;bytes-&gt;(按拆分顺序组装)read-&gt;object的过程<br>&nbsp;其实object还是不能省略,很多人写网络程序不注重逻辑对象结构,收到的一堆bytes按一定顺序读和写就完事了,这样虽然灵活,但缺乏结构,容易造成混乱，调试起来是灾难<br>&nbsp;&nbsp; 所以结构体（或类）还是省略不了的，所以：别以为有了序列化，就不需要结构体了。</p>
<p>3.结构体存在内存对齐和CPU不兼容的问题，可以避免<br>&nbsp; 的确结构体是有内存对齐的问题,存在兼容性问题,我可以选择pack(1)把内存对齐给关闭掉,避免兼容性问题,既然选择了iocp就不打算跨平台了,可以避免结构体平台兼容的问题</p>
<p>4.结构体调试起来方便很多，减少内存拷贝，效率高<br>&nbsp; 不用序列化可write和read的过程就不需要过多考虑（少写太多代码了），read write 就好像现代社会每个人每天都要穿衣服和脱衣服一样，原始社会需要吗？其实人类进化到原始裸奔状态才是最爽快的:)<br>&nbsp; 但还是要说句公道话：有人说序列化编码解码read write 需要耗费资源, 诚然这个过程基本等于赋值和内存拷贝，那点效率损失主要还在内存拷贝上，这点效率损失很小，不能作为序列化的缺点，当然如果涉及到数据加密那将是另外一个话题</p>
<p>5.结构体貌似呆板，发送数据限制多，发送变长数据就不方便，数据组织起来也不灵活<br>&nbsp; 我想这是很多人抛弃结构体，选择用序列化方式发送和接受数据的一个很重要的原因<br>&nbsp; 但：其实对于变长结构(子结构也是变长)的问题,用结构体来实现的确很麻烦,但并不代表不能实现<br>&nbsp; 我已经实现了,而且读和写变长子结构体嵌套任意多层都不成问题,可以存储复杂变长的数据结构，<br>&nbsp; 数据就如同能自动序列化一样方便，这个应该是技术难点，但细心去做是可以实现的</p>
<p>6.关于结构体指针<br>&nbsp; 游戏里面要发送的数据内存事先分配好的，不存在指针,深度复制更不用考虑，所以内存拷贝不会出错<br>&nbsp; 如果用到指针即使用序列化来实现也会面临同样的问题也占不了多少便宜，由于C++这们语言的特点，<br>&nbsp; 不象java那样有个标准实现,对于序列化本身没有一个统一的标准，所以可想而知，有人说:boost有它的序列化的实现<br>&nbsp; 其实那个实现不见得就合适你自己，如果真要做序列化，编码和解码的仿照那个过程自己写才最为牢靠，<br>&nbsp; 哪些指针对应的内存需要序列化那些不需要序列化，是个逻辑结构，需要自己说了算才好（好像扯远了点）<br>&nbsp; 说回游戏数据，既然不用需要他用到指针，结构体用来发送数据也没问题的</p>
<p>7 平台扩充问题<br>&nbsp; 退一万步的说：换了语言就基本上换了客户端，客户端的数据组织形式都要重写<br>&nbsp; 实在不行还可以考虑用xml json 编码等等一些跨平台的解决方案，现在所写的结构体是可以用来做数据接收的，只是发送的不再是结构体而已</p>
<p>8.综上所述<br>&nbsp; 如果需要跨语言平台，不用序列化（二进制流或xml, json文本等等）根本无法实现<br>&nbsp; 序列化的优点还是非常多的.如果主要是跨平台和语言自定义读写规则,根据需要读写对象的某一部分数据,<br>&nbsp; 空间浪费少,不存在内存对齐问题等诸多优点，缺点就是拐弯抹角，代码量大，调试不方便</p>
<p><br>权衡了良久<br>&nbsp; 数据如果能组织的合理，而且没有跨语言平台的要求，用结构体也未尝不可,毕竟数据发送直来直去还是方便些，减少内存拷贝，效率也高了很多<br>&nbsp; 特别是调试起来容易太多了，衡量利弊我还是放弃了序列化，选择了原始的结构体，只是难在数据的组织（好在基本已经克服了）<br><br>我知道：序列化很好很强大，很多网络程序高手根本不屑于直接发一个逻辑结构体，用这种方式就好象是旁门左道，狗肉上不了大雅之堂一样，狗肉还是很多人喜欢吃的嘛，：）。<br><br>我还是返璞归真选择了结构体<br><br>一句话：物尽其用，用的恰当，够用就好。<br><br>如果有什么不对，敬请拍砖，莫要客气</p>
<img src ="http://www.cppblog.com/tonykee/aggbug/42829.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-02-17 12:53 <a href="http://www.cppblog.com/tonykee/archive/2008/02/17/42829.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天做了一个Struct结构，作为游戏里面的包容器来使用，可以一次发送多个逻辑结构信息了，爽啊！！！</title><link>http://www.cppblog.com/tonykee/archive/2008/01/24/41766.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Wed, 23 Jan 2008 16:21:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/01/24/41766.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/41766.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/01/24/41766.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/41766.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/41766.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 做了个包容器，一次可以发多个变长逻辑结构了体了，爽啊。&nbsp;&nbsp;<a href='http://www.cppblog.com/tonykee/archive/2008/01/24/41766.html'>阅读全文</a><img src ="http://www.cppblog.com/tonykee/aggbug/41766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-01-24 00:21 <a href="http://www.cppblog.com/tonykee/archive/2008/01/24/41766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天完成了下线通知功能</title><link>http://www.cppblog.com/tonykee/archive/2008/01/17/41328.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Thu, 17 Jan 2008 05:13:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/01/17/41328.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/41328.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/01/17/41328.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/41328.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/41328.html</trackback:ping><description><![CDATA[<p>过去用户断开，其他用户不知道，也就出现了鬼影，现在刚有时间完善了这块，某人一下线，周围的人立马就知道了，另外人物移动和周围的人物通讯，已经基本实现，只是有些细节部分还不完善。这是个细致活。还要继续加油啊～！！！</p>
<img src ="http://www.cppblog.com/tonykee/aggbug/41328.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-01-17 13:13 <a href="http://www.cppblog.com/tonykee/archive/2008/01/17/41328.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对于线程资源竞争的改进</title><link>http://www.cppblog.com/tonykee/archive/2008/01/10/40924.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Thu, 10 Jan 2008 12:36:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/01/10/40924.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/40924.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/01/10/40924.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/40924.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/40924.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 对于线程资源共用问题，实际上也没有一个最完美的解决方案，没有最适合的，只有根据情况来分析，找合适的方法，我最近在做角色之间的位置信息交换，已经实现了一部分了。感觉很爽&nbsp;&nbsp;<a href='http://www.cppblog.com/tonykee/archive/2008/01/10/40924.html'>阅读全文</a><img src ="http://www.cppblog.com/tonykee/aggbug/40924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-01-10 20:36 <a href="http://www.cppblog.com/tonykee/archive/2008/01/10/40924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程中MutiRead/SingleWrite互斥的实现（原创）</title><link>http://www.cppblog.com/tonykee/archive/2008/01/09/40766.html</link><dc:creator>李侃</dc:creator><author>李侃</author><pubDate>Tue, 08 Jan 2008 17:10:00 GMT</pubDate><guid>http://www.cppblog.com/tonykee/archive/2008/01/09/40766.html</guid><wfw:comment>http://www.cppblog.com/tonykee/comments/40766.html</wfw:comment><comments>http://www.cppblog.com/tonykee/archive/2008/01/09/40766.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/tonykee/comments/commentRss/40766.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tonykee/services/trackbacks/40766.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 多线程中MutiRead/SingleWrite互斥的实现（原创），用非信号量来实现，用户模式，非内核模式，实现高效的线程调度&nbsp;&nbsp;<a href='http://www.cppblog.com/tonykee/archive/2008/01/09/40766.html'>阅读全文</a><img src ="http://www.cppblog.com/tonykee/aggbug/40766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tonykee/" target="_blank">李侃</a> 2008-01-09 01:10 <a href="http://www.cppblog.com/tonykee/archive/2008/01/09/40766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>