<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>My Pool</title>
	<atom:link href="http://www.hlouis.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hlouis.com</link>
	<description>Help, I can&#039;t swimming......</description>
	<lastBuildDate>Tue, 04 May 2010 15:27:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CEGUI Font module Hack</title>
		<link>http://www.hlouis.com/develop/cegui-font-module-hack/</link>
		<comments>http://www.hlouis.com/develop/cegui-font-module-hack/#comments</comments>
		<pubDate>Tue, 04 May 2010 15:27:10 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/develop/cegui-font-module-hack/</guid>
		<description><![CDATA[不知道这种修改算不算得上Hack，为了能让CEGUI在亚洲系字体上能有更好的表现，需要将他的字体模块的缓冲机制（主要是Freetype字体类型）做一个比较大的修改，主要修改的内容如下：
初始化时间过长
CEGUI在初始化的时候，会便利一个字体中所有的Glyph，并在d_cp_map容器中初始化所有的FontGlyph对象。这个在英文字体下没有什么问题，因为一个字体中大约只有几百Glyph，但是在中文字体中这个值一般是65535个，所以初始化的时间过长。准备废除这个初始化的过程。
CEGUI使用一个bitmap，d_glyphPageLoaded作为一个codepoint有没有载入的标志，在这里废弃这个变量，直接使用d_cp_map容器中有没有对应的FontGlyph对象作为这个codepoint有没有载入的标志。
字体缓冲的贴图占用过多
CEGUI中的字体缓冲有一个算法，就是把字体中的Glyph分页，每个页是256个文字，一旦要渲染一个文字的时候，就把这个文字前后一共256个Glyph都渲染到一张贴图上。对于英文字体来说这样不是问题，一个字体最多渲染5到6张贴图就完事了，而且采用这种策略渲染好的贴图就不需要修改了。但是对于中文字体来说这不是一个好的策略，中文字体中文字个数繁多，而且不是采用使用频率在字体中排列的，你渲染的一个文字的前后255个文字说不定在整个过程中就不会使用得到，如果讨论在极端情况下，一个中文字体一共需要65535/256=256张贴图才可以完整的渲染完，这样我们可怜的显存里面就全部都是文字了，明显不可以接受。
计划使用一个简单的缓冲机制，就是一开始设定好一个字体可以使用多少张缓冲贴图，和每张贴图的尺寸（这里暂定512*512）。这样的策略实现起来比较简单，相对来说修改的代码量也不是很大，缺点是：

CEGUI的贴图接口中并没有锁定或修改已存在的贴图内容，需要自己实现。
原始的贴图生成之后不需要修改了，现在需要经常修改，会有一定的效率损失。

]]></description>
			<content:encoded><![CDATA[<p>不知道这种修改算不算得上Hack，为了能让CEGUI在亚洲系字体上能有更好的表现，需要将他的字体模块的缓冲机制（主要是Freetype字体类型）做一个比较大的修改，主要修改的内容如下：</p>
<h2><strong>初始化时间过长</strong></h2>
<p>CEGUI在初始化的时候，会便利一个字体中所有的Glyph，并在d_cp_map容器中初始化所有的FontGlyph对象。这个在英文字体下没有什么问题，因为一个字体中大约只有几百Glyph，但是在中文字体中这个值一般是65535个，所以初始化的时间过长。准备废除这个初始化的过程。</p>
<p>CEGUI使用一个bitmap，d_glyphPageLoaded作为一个codepoint有没有载入的标志，在这里废弃这个变量，直接使用d_cp_map容器中有没有对应的FontGlyph对象作为这个codepoint有没有载入的标志。</p>
<h2><strong>字体缓冲的贴图占用过多</strong></h2>
<p>CEGUI中的字体缓冲有一个算法，就是把字体中的Glyph分页，每个页是256个文字，一旦要渲染一个文字的时候，就把这个文字前后一共256个Glyph都渲染到一张贴图上。对于英文字体来说这样不是问题，一个字体最多渲染5到6张贴图就完事了，而且采用这种策略渲染好的贴图就不需要修改了。但是对于中文字体来说这不是一个好的策略，中文字体中文字个数繁多，而且不是采用使用频率在字体中排列的，你渲染的一个文字的前后255个文字说不定在整个过程中就不会使用得到，如果讨论在极端情况下，一个中文字体一共需要65535/256=256张贴图才可以完整的渲染完，这样我们可怜的显存里面就全部都是文字了，明显不可以接受。</p>
<p>计划使用一个简单的缓冲机制，就是一开始设定好一个字体可以使用多少张缓冲贴图，和每张贴图的尺寸（这里暂定512*512）。这样的策略实现起来比较简单，相对来说修改的代码量也不是很大，缺点是：</p>
<ol>
<li>CEGUI的贴图接口中并没有锁定或修改已存在的贴图内容，需要自己实现。</li>
<li>原始的贴图生成之后不需要修改了，现在需要经常修改，会有一定的效率损失。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/cegui-font-module-hack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First blog from iPad</title>
		<link>http://www.hlouis.com/diary/firstblogfromipad/</link>
		<comments>http://www.hlouis.com/diary/firstblogfromipad/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 15:16:19 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=129</guid>
		<description><![CDATA[I&#8217;m still trying to get input method working, so this is the Twitter like post.  
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still trying to get input method working, so this is the Twitter like post. <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/firstblogfromipad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Checkout 解封纪实</title>
		<link>http://www.hlouis.com/diary/google-checkout-reactive/</link>
		<comments>http://www.hlouis.com/diary/google-checkout-reactive/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 11:16:00 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/google-checkout-reactive/</guid>
		<description><![CDATA[记得Nexus one刚刚出现的时候，就很激动的去使用google checkout下订单，下单之前了解清楚需要使用香港的收货地址，也找了常住香港的朋友，结果却悲剧的被google锁了账号，估计是我的信用卡的问题。于是将想到了去申述。这篇主要介绍一下如何进行申述的，帮助也有同样经历的人解决checkout被ban的问题。
其实把我的账户ban掉的原因很简单，就是我的信用卡的资料不对。不知道什么原因，google checkout内部支持的信用卡的国家地区选项里面吧中国剔除了（之前是有的，我肯定）于是我们就只能选用不正确的国家地区：香港。
我是2010-1-19日下的订单，三天之后checkout账户就被ban了，登陆checkout账户之后就提示我进行申述，于是我就准备了他要求的两种资料：

你个人的信息，可以是身份证或者是护照的扫描件，我选择的是护照的扫描件 
可以证明你信用卡归属和billing address的信息，我们的billing address本来就是不正确的，所以我扫描了我的招行信用卡的账单和我的信用卡的正面（卡号的前9位遮住） 
其他信息 

这个其他信息非常重要，我写了一篇很热情洋溢的信，由于我的英文写作很差，所以破费周折，原文如下：
&#160; I&#8217;m this credit card&#8217;s holder and I have left the correct card information. But the billing address I left was not match my bank billing address. Because there is no option &#34;China&#34; in the combobox when I was filling the billing adress form so I left [...]]]></description>
			<content:encoded><![CDATA[<p>记得Nexus one刚刚出现的时候，就很激动的去使用google checkout下订单，下单之前了解清楚需要使用香港的收货地址，也找了常住香港的朋友，结果却悲剧的被google锁了账号，估计是我的信用卡的问题。于是将想到了去申述。这篇主要介绍一下如何进行申述的，帮助也有同样经历的人解决checkout被ban的问题。</p>
<p>其实把我的账户ban掉的原因很简单，就是我的信用卡的资料不对。不知道什么原因，google checkout内部支持的信用卡的国家地区选项里面吧中国剔除了（之前是有的，我肯定）于是我们就只能选用不正确的国家地区：香港。</p>
<p>我是2010-1-19日下的订单，三天之后checkout账户就被ban了，登陆checkout账户之后就提示我进行申述，于是我就准备了他要求的两种资料：</p>
<ol>
<li>你个人的信息，可以是身份证或者是护照的扫描件，我选择的是护照的扫描件 </li>
<li>可以证明你信用卡归属和billing address的信息，我们的billing address本来就是不正确的，所以我扫描了我的招行信用卡的账单和我的信用卡的正面（卡号的前9位遮住） </li>
<li>其他信息 </li>
</ol>
<p>这个其他信息非常重要，我写了一篇很热情洋溢的信，由于我的英文写作很差，所以破费周折，原文如下：</p>
<blockquote><p>&#160; I&#8217;m this credit card&#8217;s holder and I have left the correct card information. But the billing address I left was not match my bank billing address. Because there is no option &quot;China&quot; in the combobox when I was filling the billing adress form so I left the address where I was living one year ago when I&#8217;m working in HK. But then I moved to mainland China Shanghai. </p>
<p>&#160; Under this special situation I am not able to provide the billing address of HK since I am now living in Shanghai and the bank send the bills to my new address in Shanghai. I sincerely hope you can understand my special situation and reactivate this account,so that I can place order again and ship Nuxus one to my uncle with his HK address. </p>
<p>&#160; Thanks for your time and pls let me know if you want more documents to verify this account.</p>
</blockquote>
<p>建议大家不要原文照抄，一定要修改修改。。。。。而且更加重要的事情，人家三天后就回信了，表明，就是要ban你，回信原文如下：</p>
<blockquote><p>Hello Luyi,      <br />Upon review of your account, it appears that your information corresponds       <br />with a currently unsupported billing country. To view a list of supported       <br />billing countries, check the Location: drop-down menu on the sign-up page.       <br />As a result, your account associated with <font color="#f26522"><a href="mailto:xxxx@gmail.com">xxxx@gmail.com</a></font> has been       <br />suspended and the order(s) have been cancelled.       <br />Any pending and future transactions made with this account will not be       <br />processed.       <br />We understand that order cancellations under these circumstances can be       <br />disappointing. Please know that we look forward to offering more options       <br />in the near future. We regret any inconvenience that this may cause and       <br />appreciate your understanding.</p>
</blockquote>
<p>于是我就组织了一份措辞稍稍严厉的信（不容易啊，就我这个英文水平），回复给了这个客服，原文如下：</p>
<blockquote><p>Hi Mary</p>
<p>I totally understand why my account is suspended. As required, I have proved the credit card ownership, I think there is no reason to suspend my account any longer. You can drop my order, but cannot freeze it forever.      <br />I just got a HSBC credit card which is issued in Hongkong two weeks ago, I think this one could be use in my checkout account. I love my Google account as <a href="mailto:lxxxxxx@gmail.com">xxxxxx@gmail.com</a>. Please give me a chance to reactive it with checkout service. I don&#8217;t want to register another new account just for the stupid checkout issue.</p>
<p>&#160;</p>
</blockquote>
<p>结果放了两个礼拜都没有人理我，所以我估计这个email账号是一个noreply的账户，可惜给我的mail里面没有说明，于是就又去checkout的申述页面，提交了和上次一样的证明信息，并把和这位客服的来回mail放到了其他信息中。结果，第二天早上就收到了账户解封的mail。</p>
<p>我觉得没啥很难得地方，就是要和他们沟通，主要是表明，自己就是信用卡的主人，没有欺诈，祝大家好运 <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/google-checkout-reactive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Domain Change</title>
		<link>http://www.hlouis.com/diary/domainchange/</link>
		<comments>http://www.hlouis.com/diary/domainchange/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 01:55:35 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=109</guid>
		<description><![CDATA[因为一些众所周知的原因，我决定要放弃我的.cn的域名了，所以我的域名正式更改：
www.mypool.cn ======&#62;&#62;&#62;&#62;  www.hlouis.com
如果有人订阅过我的blog，请将订阅地址更新为：
http://www.hlouis.com/feed/
目前我的cn域名会持续到今年8月份到期，（当然，也可能在中途的任意时刻被停止解析）这段时间内这两个域名会同时指向我现在的网站，所以理论上会有很长的一段过渡时期。。。。。
]]></description>
			<content:encoded><![CDATA[<p>因为一些众所周知的原因，我决定要放弃我的<strong>.cn</strong>的域名了，所以我的域名正式更改：</p>
<h3><span style="color: #c0c0c0;">www.mypool.cn</span> ======&gt;&gt;&gt;&gt;  <strong>www.hlouis.com</strong></h3>
<p>如果有人订阅过我的blog，请将订阅地址更新为：</p>
<p>http://www.hlouis.com/feed/</p>
<p>目前我的cn域名会持续到今年8月份到期，（当然，也可能在中途的任意时刻被停止解析）这段时间内这两个域名会同时指向我现在的网站，所以理论上会有很长的一段过渡时期。。。。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/domainchange/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lua can&#8217;t do math?</title>
		<link>http://www.hlouis.com/develop/lua-cant-do-math/</link>
		<comments>http://www.hlouis.com/develop/lua-cant-do-math/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 04:36:13 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Develop]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/develop/lua-cant-do-math/</guid>
		<description><![CDATA[今天把项目中所有使用的脚本从python替换到lua，一切看起来很美，不过最后测试的时候发现一个非常诡异的问题，具体lua语句如下：
print("simple test: ")
print((10000 + 123456789) - 123456789)
程序打印出来的值竟然是10003，顿时被雷到了。虽然我知道lua用的是double作为基础的lua_number，但是人家已经很耐心的教育我们double是双精度类型，不会出现什么四舍五入的问题。于是打开linux上的终端运行lua进行同样的计算，这次得到的是正确的结果：10000。
想想也知道lua不会有这种低级的错误的，要不还不立刻被人骂死，于是开始找自己的问题，首先怀疑是我们的lua嵌入包裹代码的问题，仔细review了一遍代码，觉得不会影响到这么底层的问题。接着开始做实验，发现在服务器上的同样lua代码，运行的结果是正确的。经过无尽的折腾，最后发现了这么一个事实：
在directX的sdk文档里面，D3DCREATE这个条目里面有这么一条：
D3DCREATE_FPU_PRESERVE Set the precision for Direct3D floating-point calculations to the precision used by the calling thread. If you do not specify this flag, Direct3D defaults to single-precision round-to-nearest mode for two reasons:
- Double-precision mode will reduce Direct3D performance.
- Portions of Direct3D assume floating-point unit exceptions are masked; unmasking these [...]]]></description>
			<content:encoded><![CDATA[<p>今天把项目中所有使用的脚本从python替换到lua，一切看起来很美，不过最后测试的时候发现一个非常诡异的问题，具体lua语句如下：</p>
<pre class="brush:js">print("simple test: ")
print((10000 + 123456789) - 123456789)</pre>
<p>程序打印出来的值竟然是10003，顿时被雷到了。虽然我知道lua用的是double作为基础的lua_number，但是人家已经很耐心的教育我们double是双精度类型，不会出现什么四舍五入的问题。于是打开linux上的终端运行lua进行同样的计算，这次得到的是正确的结果：10000。</p>
<p>想想也知道lua不会有这种低级的错误的，要不还不立刻被人骂死，于是开始找自己的问题，首先怀疑是我们的lua嵌入包裹代码的问题，仔细review了一遍代码，觉得不会影响到这么底层的问题。接着开始做实验，发现在服务器上的同样lua代码，运行的结果是正确的。经过无尽的折腾，最后发现了这么一个事实：</p>
<p>在directX的sdk文档里面，D3DCREATE这个条目里面有这么一条：</p>
<blockquote><p><strong>D3DCREATE_FPU_PRESERVE</strong> Set the precision for Direct3D floating-point calculations to the precision used by the calling thread. If you do not specify this flag, Direct3D defaults to single-precision round-to-nearest mode for two reasons:<br />
- Double-precision mode will reduce Direct3D performance.<br />
- Portions of Direct3D assume floating-point unit exceptions are masked; unmasking these exceptions may result in undefined behavior</p></blockquote>
<p>D3D默认在创建设备的时候，会把双精度改成单精度，增加渲染的效率，所以lua也被殃及了，这也算是蝴蝶效应的一个体现吧。。。。。</p>
<p>恶心的问题只要原因找到了解决总是相对容易的，现在有两个方案：</p>
<ol>
<li>将lua_number定义为int，缺点是lua内就不能使用小数</li>
<li>在D3D初始化的时候添加参数，让他不要改变计算精度，缺点是不知道对性能有多大影响</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/lua-cant-do-math/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Get rid of memory bugs</title>
		<link>http://www.hlouis.com/develop/get-rid-of-memory-bugs/</link>
		<comments>http://www.hlouis.com/develop/get-rid-of-memory-bugs/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 13:43:49 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Develop]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=100</guid>
		<description><![CDATA[大型的C/C++程序做到最后，bug高发的时期过去之后，一般来说会出现的问题都是很妖的。最最常见的现象就是一下几种：

调用栈全部混乱，一堆问号出现在这里，你明明知道自己编译的时候有放入符号，现在却什么信息都看不到 
莫名其妙的调用了一个代码里面没有调用的函数 
重复的free或者delete某块内存，然后崩溃 
部分静态或者全局的数据混乱了，代码里面除了初始化就没啥地方写过他们了 
莫名的某个对象的数据全部混乱了 

 
其实有经验的程序员看到我上面这堆牢骚就知道，归根结底，这些问题都是一个原因：内存混乱。可以直接操作内存是C/C++的效率之源也是一切的罪恶之源。没有个两三年的编程经验，很难深刻的理解内存、指针和引用这些看起来没啥深奥的问题。关于可能出现的内存混乱我大概的归纳一下：

使用没有初始化的内存 
内存越界 
内存泄漏

为了理解如何处理这些情况，我们先稍微总结一下程序的内存的使用会出现在什么地方：

静态，全局内存：静态和全局对象会在main函数之前由libc进行初始化和分配，他们因该会出现在运行的数据段上，一般来说是数据段的开头部分。问题2， 4和5可能由这种内存的混乱引起。 
栈内存：基本上可以认为是局部变量初始化的内存了，在程序入栈的时候分配，出栈的时候丢弃。这种内存混乱可能会引起问题1, 2, 4, 5 
堆内存：由malloc、new分配，由free、delete回收的内存。这种内存混乱的话，会引起2、3、4、5 

基本上想要彻底在机制上解决内存问题，肯定是没有希望的，因为如果这是可行的，那么早就有nb的人做出来，并放到标准里面了。于是他们做出了java。。。。。所以我们现在追求的就是如何能够快速的追踪到问题的源头。
不像是其他的逻辑bug，内存混乱引起的问题，现象是千奇百怪的，而且发生问题的源头往往和现象不在同一个调用栈里面，或者是整个调用栈全部乱掉，让你无从可查。所以必须要使用一些其他手段来帮助我们。根据不同的内存使用种类，我说一下自己的思路，和目前已经有的做法：

堆内存：为什么先从堆开始说起，因为堆上的内存分配和删除是完全控制在我们自己手里面的，说实话，这块东西早就有很多的工具和代码进行跟踪保护和分配了。而且相关的原理基本相通。 

最完整的办法解决这个问题是建立自己的内存管理体系，使用内存池，托管系统的malloc、free或者是new、delete。这样不仅仅可以在犯错的时候我们有机会去监测或者记录。还可以通过内存池来增加系统的效率。 
如果暂时没有成体系的内存管理系统，也可以使用第三方工具，比如非侵入式的valgrin或者是编译到代码里面的efence。这些工具都可以很好的帮你监控报告这些内存的混乱。 
对于内存溢出这个问题，不论是自己的内存管理体系还是第三方的监测工具，基本上都是一个原理。在分配内存的时候多申请一定的字节，比如20个bytes，并将他们初始化为一些特殊的字节。然后去检查这块内存有没有变化。如果有变化就是出现了溢出。最佳的方法是用cpu或者是操作系统提供的内存保护机制，这样一旦有任何的要对这块内存的操作指令，就会立刻break出来，这时再用gdb等的debug工具就可以直接查看调用栈找到元凶。较差的方法是定期或者是析构的时候监测，不过这样效果不好，只能知道到底有没有溢出，或者是哪块内存溢出。到底是谁干的，还是要大海捞针。 


栈内存：栈内存的混乱基本上会死的很直接，不会让问题慢慢的慢慢的变大。不过栈内存的特殊性，会导致他把案发现场的很多痕迹抹去，因为栈混乱了，所以你看到的调用栈完全是混乱的。你不知道出现的原因是什么。

对于这种情况，我暂时使用了一种看起来有点简陋的方法。就是使用一个buffer来手动的存储目前的调用栈。入栈的时候通过宏把函数名加入buffer，退栈的时候通过宏把函数名移除。坏处是增加了入栈出栈的代价，同时要记录的函数需要在开始和结束的时候添加宏。 


静态、全局内存混乱：这块是比较复杂的，特别是出现了这种内存的溢出，他会悄无声息的抹去你很多的全局，静态变量，但是系统依然可以运行，不过很多依赖于这些变量的行为都会变的无法预测，天知道这时候会做出什么变态的事情。同时这种内存的分配是在进入main之前发生的，我们完全无能为力。想要对付这种内存我建议。。。。。

在开发小组中规定。。。。不要使用这种内存。 




]]></description>
			<content:encoded><![CDATA[<p><font face="微软雅黑">大型的C/C++程序做到最后，bug高发的时期过去之后，一般来说会出现的问题都是很妖的。最最常见的现象就是一下几种：</font></p>
<ol>
<li><font face="微软雅黑"><span style="background-color: #ffffff">调用栈全部混乱，一堆问号出现在这里，你明明知道自己编译的时候有放入符号，现在却什么信息都看不到</span> </font></li>
<li><font face="微软雅黑"><span style="background-color: #ffffff">莫名其妙的调用了一个代码里面没有调用的函数</span> </font></li>
<li><font face="微软雅黑"><span style="background-color: #ffffff">重复的free或者delete某块内存，然后崩溃</span> </font></li>
<li><font face="微软雅黑"><span style="background-color: #ffffff">部分静态或者全局的数据混乱了，代码里面除了初始化就没啥地方写过他们了</span> </font></li>
<li><font face="微软雅黑"><span style="background-color: #ffffff">莫名的某个对象的数据全部混乱了</span> </font></li>
</ol>
<p> <span id="more-100"></span>
<p><font face="微软雅黑">其实有经验的程序员看到我上面这堆牢骚就知道，归根结底，这些问题都是一个原因：<strong>内存混乱</strong>。可以直接操作内存是C/C++的效率之源也是一切的罪恶之源。没有个两三年的编程经验，很难深刻的理解内存、指针和引用这些看起来没啥深奥的问题。关于可能出现的内存混乱我大概的归纳一下：</font></p>
<ul>
<li><font face="微软雅黑">使用没有初始化的内存 </font></li>
<li><font face="微软雅黑">内存越界 </font></li>
<li><font face="微软雅黑">内存泄漏</font></li>
</ul>
<p><font face="微软雅黑">为了理解如何处理这些情况，我们先稍微总结一下程序的内存的使用会出现在什么地方：</font></p>
<ul>
<li><font face="微软雅黑">静态，全局内存：静态和全局对象会在main函数之前由libc进行初始化和分配，他们因该会出现在运行的数据段上，一般来说是数据段的开头部分。问题2， 4和5可能由这种内存的混乱引起。 </font></li>
<li><font face="微软雅黑">栈内存：基本上可以认为是局部变量初始化的内存了，在程序入栈的时候分配，出栈的时候丢弃。这种内存混乱可能会引起问题1, 2, 4, 5 </font></li>
<li><font face="微软雅黑">堆内存：由malloc、new分配，由free、delete回收的内存。这种内存混乱的话，会引起2、3、4、5 </font></li>
</ul>
<p><font face="微软雅黑">基本上想要彻底在机制上解决内存问题，肯定是没有希望的，因为如果这是可行的，那么早就有nb的人做出来，并放到标准里面了。于是他们做出了java。。。。。所以我们现在追求的就是如何能够快速的追踪到问题的源头。</font></p>
<p><font face="微软雅黑">不像是其他的逻辑bug，内存混乱引起的问题，现象是千奇百怪的，而且发生问题的源头往往和现象不在同一个调用栈里面，或者是整个调用栈全部乱掉，让你无从可查。所以必须要使用一些其他手段来帮助我们。根据不同的内存使用种类，我说一下自己的思路，和目前已经有的做法：</font></p>
<ul>
<li><font face="微软雅黑">堆内存：为什么先从堆开始说起，因为堆上的内存分配和删除是完全控制在我们自己手里面的，说实话，这块东西早就有很多的工具和代码进行跟踪保护和分配了。而且相关的原理基本相通。 </font>
<ul>
<li><font face="微软雅黑">最完整的办法解决这个问题是建立自己的内存管理体系，使用内存池，托管系统的malloc、free或者是new、delete。这样不仅仅可以在犯错的时候我们有机会去监测或者记录。还可以通过内存池来增加系统的效率。</font> </li>
<li><font face="微软雅黑">如果暂时没有成体系的内存管理系统，也可以使用第三方工具，比如非侵入式的valgrin或者是编译到代码里面的efence。这些工具都可以很好的帮你监控报告这些内存的混乱。</font> </li>
<li><font face="微软雅黑">对于内存溢出这个问题，不论是自己的内存管理体系还是第三方的监测工具，基本上都是一个原理。在分配内存的时候多申请一定的字节，比如20个bytes，并将他们初始化为一些特殊的字节。然后去检查这块内存有没有变化。如果有变化就是出现了溢出。最佳的方法是用cpu或者是操作系统提供的内存保护机制，这样一旦有任何的要对这块内存的操作指令，就会立刻break出来，这时再用gdb等的debug工具就可以直接查看调用栈找到元凶。较差的方法是定期或者是析构的时候监测，不过这样效果不好，只能知道到底有没有溢出，或者是哪块内存溢出。到底是谁干的，还是要大海捞针。</font> </li>
</ul>
</li>
<li><font face="微软雅黑">栈内存：栈内存的混乱基本上会死的很直接，不会让问题慢慢的慢慢的变大。不过栈内存的特殊性，会导致他把案发现场的很多痕迹抹去，因为栈混乱了，所以你看到的调用栈完全是混乱的。你不知道出现的原因是什么。</font>
<ul>
<li><font face="微软雅黑">对于这种情况，我暂时使用了一种看起来有点简陋的方法。就是使用一个buffer来手动的存储目前的调用栈。入栈的时候通过宏把函数名加入buffer，退栈的时候通过宏把函数名移除。坏处是增加了入栈出栈的代价，同时要记录的函数需要在开始和结束的时候添加宏。</font> </li>
</ul>
</li>
<li><font face="微软雅黑">静态、全局内存混乱：这块是比较复杂的，特别是出现了这种内存的溢出，他会悄无声息的抹去你很多的全局，静态变量，但是系统依然可以运行，不过很多依赖于这些变量的行为都会变的无法预测，天知道这时候会做出什么变态的事情。同时这种内存的分配是在进入main之前发生的，我们完全无能为力。想要对付这种内存我建议。。。。。</font>
<ul>
<li><font face="微软雅黑">在开发小组中规定。。。。<strong>不要使用这种内存</strong>。</font> </li>
</ul>
</li>
</ul>
<p><font face="微软雅黑"></font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/get-rid-of-memory-bugs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Test Live writer 2009</title>
		<link>http://www.hlouis.com/diary/test-live-writer-2009/</link>
		<comments>http://www.hlouis.com/diary/test-live-writer-2009/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 12:10:37 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/test-live-writer-2009/</guid>
		<description><![CDATA[同事帮我画的两张卡通头像，谢谢gary同学~
 
]]></description>
			<content:encoded><![CDATA[<p>同事帮我画的两张卡通头像，谢谢gary同学~</p>
<p><a href="http://www.hlouis.com/hlouis_com/wp-content/uploads/2009/01/head1-by-gary.png"><img title="head1_by_gary" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="183" alt="head1_by_gary" src="http://www.hlouis.com/hlouis_com/wp-content/uploads/2009/01/head1-by-gary-thumb.png" width="244" border="0" /></a> <a href="http://www.hlouis.com/hlouis_com/wp-content/uploads/2009/01/head2-by-gary.png"><img title="head2_by_gary" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="184" alt="head2_by_gary" src="http://www.hlouis.com/hlouis_com/wp-content/uploads/2009/01/head2-by-gary-thumb.png" width="244" border="0" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/test-live-writer-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fix IBus Openoffic and Awesome</title>
		<link>http://www.hlouis.com/develop/linux/fix-ibus-openoffic-and-awesome/</link>
		<comments>http://www.hlouis.com/develop/linux/fix-ibus-openoffic-and-awesome/#comments</comments>
		<pubDate>Wed, 31 Dec 2008 06:44:58 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=92</guid>
		<description><![CDATA[Add following line to soffice start script
# IBUS was confilict with OOO3 under awesomedon&#8217;t know why, but add the blow  
# line, everything OK then~ cheers
OOO_FORCE_DESKTOP=gnome export OOO_FORCE_DESKTOP 
]]></description>
			<content:encoded><![CDATA[<p>Add following line to soffice start script</p>
<blockquote><p># IBUS was confilict with OOO3 under awesomedon&#8217;t know why, but add the blow  <br />
# line, everything OK then~ cheers</p>
<p>OOO_FORCE_DESKTOP=gnome export OOO_FORCE_DESKTOP </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/linux/fix-ibus-openoffic-and-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[ZT]Line feed and Carriage return</title>
		<link>http://www.hlouis.com/diary/ztline-feed-and-carriage-return/</link>
		<comments>http://www.hlouis.com/diary/ztline-feed-and-carriage-return/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 01:48:51 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=90</guid>
		<description><![CDATA[今天，我总算搞清楚“回车”（carriage return）和“换行”（line feed）这两个概念的来历和区别了。
在计算机还没有出现之前，有一种叫做电传打字机（Teletype Model 33）的玩意，每秒钟可以打10个字符。但是它有一个问题，就是打完一行换行的时候，要用去0.2秒，正好可以打两个字符。要是在这0.2秒里面，又有新的字符传过来，那么这个字符将丢失。
于是，研制人员想了个办法解决这个问题，就是在每行后面加两个表示结束的字符。一个叫做“回车”，告诉打字机把打印头定位在左边界；另一个叫做“换行”，告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历，从它们的英语名字上也可以看出一二。
后来，计算机发明了，这两个概念也就被般到了计算机上。那时，存储器很贵，一些科学家认为在每行结尾加两个字符太浪费了，加一个就可以。于是，就出现了分歧。
Unix 系统里，每行结尾只有“&#60;换行&#62;”，即“\n”；Windows系统里面，每行结尾是“&#60;换行&#62;&#60;回车&#62;”，即“ \n\r”；Mac系统里，每行结尾是“&#60;回车&#62;”。一个直接后果是，Unix/Mac系统下的文件在Windows里打开的话，所有文字会变成一行；而Windows里的文件在Unix/Mac下打开的话，在每行的结尾可能会多出一个^M符号。
c语言编程时（windows系统）
\r 就是return 回到 本行 行首 这就会把这一行以前的输出 覆盖掉
如：
int main() {
cout &#60;&#60; &#8220;hahaha&#8220; &#60;&#60; &#8220;\r&#8220; &#60;&#60; &#8220;xixi&#8220; ;
}
最后只显示 xixi 而 hahaha 背覆盖了
\n 是回车＋换行 把光标 先移到 行首 然后换到下一行 也就是 下一行的行首拉
int main() {
cout &#60;&#60; &#8220;hahaha&#8220; &#60;&#60; &#8220;\n&#8220; &#60;&#60; &#8220;xixi&#8220; ;
}
则 显示
hahaha
xixi 
]]></description>
			<content:encoded><![CDATA[<p><span>今天，我总算搞清楚“回车”（carriage </span><span>return</span><span>）和“换行”（line feed）这两个概念的来历和区别了。<br />
在计算机还没有出现之前，有一种叫做电传打字机（Teletype Model </span><span>33</span><span>）的玩意，每秒钟可以打10个字符。但是它有一个问题，就是打完一行换行的时候，要用去0.2秒，正好可以打两个字符。要是在这0.2秒里面，又有新的字符传过来，那么这个字符将丢失。</p>
<p>于是，研制人员想了个办法解决这个问题，就是在每行后面加两个表示结束的字符。一个叫做“回车”，告诉打字机把打印头定位在左边界；另一个叫做“换行”，告诉打字机把纸向下移一行。</p>
<p>这就是“换行”和“回车”的来历，从它们的英语名字上也可以看出一二。</p>
<p>后来，计算机发明了，这两个概念也就被般到了计算机上。那时，存储器很贵，一些科学家认为在每行结尾加两个字符太浪费了，加一个就可以。于是，就出现了分歧。</p>
<p>Unix 系统里，每行结尾只有“</span><span>&lt;</span><span>换行</span><span>&gt;</span><span>”，即“\n”；Windows系统里面，每行结尾是“</span><span>&lt;</span><span>换行</span><span>&gt;&lt;</span><span>回车</span><span>&gt;</span><span>”，即“ \n\r”；Mac系统里，每行结尾是“</span><span>&lt;</span><span>回车</span><span>&gt;</span><span>”。一个直接后果是，Unix</span><span>/</span><span>Mac系统下的文件在Windows里打开的话，所有文字会变成一行；而Windows里的文件在Unix</span><span>/</span><span>Mac下打开的话，在每行的结尾可能会多出一个</span><span>^</span><span>M符号。</p>
<p>c语言编程时（windows系统）</p>
<p>\r 就是return 回到 本行 行首 这就会把这一行以前的输出 覆盖掉</p>
<p>如：<br />
</span><span>int</span><span> main() {</p>
<p>cout </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>hahaha</span><span>&#8220;</span><span> </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>\r</span><span>&#8220;</span><span> </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>xixi</span><span>&#8220;</span><span> ;</p>
<p>}<br />
最后只显示 xixi 而 hahaha 背覆盖了</p>
<p>\n 是回车＋换行 把光标 先移到 行首 然后换到下一行 也就是 下一行的行首拉</p>
<p></span><span>int</span><span> main() {</p>
<p>cout </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>hahaha</span><span>&#8220;</span><span> </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>\n</span><span>&#8220;</span><span> </span><span>&lt;&lt;</span><span> </span><span>&#8220;</span><span>xixi</span><span>&#8220;</span><span> ;</p>
<p>}<br />
则 显示<br />
hahaha<br />
xixi </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/ztline-feed-and-carriage-return/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Email to real letters</title>
		<link>http://www.hlouis.com/ideas/email-to-real-letters/</link>
		<comments>http://www.hlouis.com/ideas/email-to-real-letters/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 06:35:38 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Ideas]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=85</guid>
		<description><![CDATA[Web 0.2 site, turn your email to real letters, charge U by letters count, you can choose the printing font style, or even you can let some people, real people write the letter for U!
]]></description>
			<content:encoded><![CDATA[<p>Web 0.2 site, turn your email to real letters, charge U by letters count, you can choose the printing font style, or even you can let some people, real people write the letter for U!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/ideas/email-to-real-letters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Script RPC</title>
		<link>http://www.hlouis.com/design/script-rpc/</link>
		<comments>http://www.hlouis.com/design/script-rpc/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 06:30:52 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[mess]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/?p=83</guid>
		<description><![CDATA[In c/c++ server design, event call always the painful part. How to register callback functions:

Use global or static method? 
Use event class and vritual method call?
How to handle the memory between caller and callee?
How to pass context, use pointer? use handle?

So many questions need to be taken care, but, maybe under the script world, life will [...]]]></description>
			<content:encoded><![CDATA[<p>In c/c++ server design, event call always the painful part. How to register callback functions:</p>
<ul>
<li>Use global or static method? </li>
<li>Use event class and vritual method call?</li>
<li>How to handle the memory between caller and callee?</li>
<li>How to pass context, use pointer? use handle?</li>
</ul>
<div>So many questions need to be taken care, but, maybe under the script world, life will be more easy&#8230;..</div>
<div></div>
<div>Lua thoughts:</div>
<div>
<ul>
<li>Use coroutines, when do an async call, we stop this coroutine, when callback, we resume the coroutine, so each context is there, we do not need pass anything, only the coroutine handler.</li>
<li>Functional languange easy to pass or generate callback function, so handler some very simple callback event, are very convenient.</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/script-rpc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SNS BBS way</title>
		<link>http://www.hlouis.com/diary/sns-bbs-way/</link>
		<comments>http://www.hlouis.com/diary/sns-bbs-way/#comments</comments>
		<pubDate>Wed, 20 Feb 2008 05:37:59 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/sns-bbs-way/</guid>
		<description><![CDATA[SNS和BBS每天累计着大量用户的活动，这些活动有很大一部分被沉淀下来成为有用的资讯。比如说怎么买电话卡，怎么做菜，又或者如何辅导孩子，某种型号的手机出了何种问题如何维修，如何给游戏机添加冷却装置。
这些积累都是SNS和BBS最有价值的部分，新用户往往是为了寻找这样的信息而进行注册和翻阅的。时间越悠久的社区这种有价值的信息就越多。然而我们的BBS和SNS几乎没有提供任何有用的工具帮助用户们来组织，保存分享这样的信息，而是依靠用户自己进行整理和归纳，唯一提供的功能大概就是“置顶”这个功能了。
如果SNS和BBS可以有效的整理归纳和更新这样的信息，肯定可以从中得到好处。让用户更加容易找到信息，可以扩大用户数量。将这些信息中提到的物品进行销售（比如水冷装置，或者某种食谱提及的配料）可以带来一定量的盈利。
]]></description>
			<content:encoded><![CDATA[<p>SNS和BBS每天累计着大量用户的活动，这些活动有很大一部分被沉淀下来成为有用的资讯。比如说怎么买电话卡，怎么做菜，又或者如何辅导孩子，某种型号的手机出了何种问题如何维修，如何给游戏机添加冷却装置。</p>
<p>这些积累都是SNS和BBS最有价值的部分，新用户往往是为了寻找这样的信息而进行注册和翻阅的。时间越悠久的社区这种有价值的信息就越多。然而我们的BBS和SNS几乎没有提供任何有用的工具帮助用户们来组织，保存分享这样的信息，而是依靠用户自己进行整理和归纳，唯一提供的功能大概就是“置顶”这个功能了。</p>
<p>如果SNS和BBS可以有效的整理归纳和更新这样的信息，肯定可以从中得到好处。让用户更加容易找到信息，可以扩大用户数量。将这些信息中提到的物品进行销售（比如水冷装置，或者某种食谱提及的配料）可以带来一定量的盈利。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/sns-bbs-way/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hard work with Soft work</title>
		<link>http://www.hlouis.com/design/hard-work-with-soft-work/</link>
		<comments>http://www.hlouis.com/design/hard-work-with-soft-work/#comments</comments>
		<pubDate>Wed, 23 Jan 2008 13:03:16 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/hard-work-with-soft-work/</guid>
		<description><![CDATA[前段时间转载过程序员的温情管理文化在 这篇文章中提出：
程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。
我非常同意这样的看法，一个程序员如果在脑袋糊涂，精神萎靡的情况下写出代码 ，往往是逻辑不清楚，只是想把事情糊弄过去，久而久之，众多的小问题就积累起来，让整个项目陷入泥潭，并进入不得不重构的境地。
一个程序员，如果一天可以集中精力，进行5个小时以上的高效工作，并在这段时间内保持思路清楚，编写出高质量的代码，我觉得他肯定已经是顶级的程序员了，精力过人并且技术扎实。对于我们这样的正常人来说，一天可以维持三到四小时这样的高效工作就已经是很了不起的事情了。对于这段高效高质时间，我们应该加以充分的利用。对于效率偏低的时间，我们应该换一个策略来进行工作，这就是我想要说的，对于程序员的工作安排，应该有Hard word和Soft work的区分。
Hard work是指，列在工作项目上的，必须要做完的东西。这些工作项目都是列在整个开发项目的日程表上，不可或缺的环节。
Soft work是指，并没有列在整个项目的开发日程表上，但是对于技术储备，思路拓展都很有帮助的任务。进行Soft work应该可以让程序员enjoy其中，毕竟如果你对学习新技术没有兴趣，估计程序员的职业也就不适合你了。
对于项目的管理人员，挑战的任务就是如何分派两种任务，如何引导程序员进行Soft work，并控制这两种工作所需消耗的时间，如何帮助程序员了解并提高自己的高效工作时间，并可以让他们在早上打开电脑之后就能很明确的知道：今天的工作是什么，哪些最重要，哪些优先级别最高。
]]></description>
			<content:encoded><![CDATA[<p>前段时间转载过<a href="http://www.mypool.cn/diary/cheng-xu-yuan-guan-li/" rel="bookmark">程序员的温情管理文化</a>在 这篇文章中提出：</p>
<blockquote><p>程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。</p></blockquote>
<p>我非常同意这样的看法，一个程序员如果在脑袋糊涂，精神萎靡的情况下写出代码 ，往往是逻辑不清楚，只是想把事情糊弄过去，久而久之，众多的小问题就积累起来，让整个项目陷入泥潭，并进入不得不重构的境地。</p>
<p>一个程序员，如果一天可以集中精力，进行5个小时以上的高效工作，并在这段时间内保持思路清楚，编写出高质量的代码，我觉得他肯定已经是顶级的程序员了，精力过人并且技术扎实。对于我们这样的正常人来说，一天可以维持三到四小时这样的高效工作就已经是很了不起的事情了。对于这段高效高质时间，我们应该加以充分的利用。对于效率偏低的时间，我们应该换一个策略来进行工作，这就是我想要说的，对于程序员的工作安排，应该有Hard word和Soft work的区分。</p>
<p>Hard work是指，列在工作项目上的，必须要做完的东西。这些工作项目都是列在整个开发项目的日程表上，不可或缺的环节。<br />
Soft work是指，并没有列在整个项目的开发日程表上，但是对于技术储备，思路拓展都很有帮助的任务。进行Soft work应该可以让程序员enjoy其中，毕竟如果你对学习新技术没有兴趣，估计程序员的职业也就不适合你了。</p>
<p>对于项目的管理人员，挑战的任务就是如何分派两种任务，如何引导程序员进行Soft work，并控制这两种工作所需消耗的时间，如何帮助程序员了解并提高自己的高效工作时间，并可以让他们在早上打开电脑之后就能很明确的知道：今天的工作是什么，哪些最重要，哪些优先级别最高。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/hard-work-with-soft-work/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>你是否经常听到楼上有弹珠掉地上的声音？</title>
		<link>http://www.hlouis.com/diary/strange-sound-in-night/</link>
		<comments>http://www.hlouis.com/diary/strange-sound-in-night/#comments</comments>
		<pubDate>Mon, 21 Jan 2008 05:20:40 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/strange-sound-in-night/</guid>
		<description><![CDATA[ 你是否经常听到楼上有弹珠掉地上的声音？


近来在互联网上看到，有人在网上做了一个调查，发现有80％的人听到过,每次都是2－3声象弹珠球跌落在地上又弹起的声音&#8230;
每次都是2－4声&#8230;.而且都是在半夜听到，声音好象还挺重的
现在的小朋友还玩弹珠吗？
并且有时还听到麻将骰子掉地的声音！
还有有时也可以听到好象一些家具搬动的声音，仿佛是人在拖一样！
以前还一直疑惑是什么原因，当时也并不怎么在意！没有深究其原因！但是通过互联网以后，发现很多朋友都似乎听到过这种来历不明的声音！！！这就奇怪了，全国各地难道都会出现这样的情形吗？？？这不是特别针对与个人的事情呀？
究竟是什么原因呢？是热膨冷缩吗？
实验一：真的跑去楼上打弹珠，发现声音根本几乎是听不到，其实地板比一般人想象中要厚得很多，顶多像文具、手表之类掉到地上的声音，如果这都听得到~那我看还得了，楼上一举一动你都听得到。
实验证明声音能否传到楼下和那个东西的重量有很大关系，也许这有声学或物理上的原因吧，在此就不探究了，总之就算刻意把弹珠很大力砸在地上~~也要夜深人静又很仔细听才听到一些(而且声音种类也不像)
实验二：一块1*1*0.17公尺的水泥块，内嵌钢筋网和两根水管
在实验室用压克力玻璃罩住里用热空气加热法；加到比室温高50度后持续90分钟，之后罩子打开浇冷水加吹风扇急速冷却，结果&#8230;&#8230;啥事也没发生~什么鬼声也没有.
实验三：同样水泥块同样步骤，这次用半虎钳+铁板把前后左右抵住卡紧；结果&#8230;&#8230;啥事又没发生~边缘有非常非常细的小小裂纹而已~什么鬼声也没有
那么~到底答案是什么??
原来元凶就是霉菌!!
是一种不完全菌纲的霉菌为主会腐蚀工业材料与水泥，好生于多细孔表面，以水泥中矿物质为食。
一般天花板是上下两层的细钢筋作支撑，在灌浆的时候其实钢筋不是笔直的被卡在水泥中，受到水泥浆的流动和重量可能会有向上或向左右的应力累积着，或着房子盖好数年后~受到地震或地基小位移等等因素，细钢筋又会产生新的应力。
在天花板的偏下层有电灯线路的管线出口，有温度与空气等等所以霉菌会沿着该孔开始逐步入侵水泥中缝细，细钢筋与水泥接触面是最理想缝细，霉菌多聚 生于此，菌丝向四周开始侵蚀成一个中空型管道。当某根有应力钢筋的周围水泥被侵蚀到一定程度后便会在中空管道中来回弹动，这就是弹珠声的来源。
所以实验下一步就刻意制作水泥块后；中间夹入比钢筋略粗的塑料棒形成中空道，水泥半干后拿出塑料管插入钢筋，再从另一端灌一些水泥固定。
事实证明，细钢筋在管道中弹动的声音和弹珠声是最像的。
这解释了以下几点
1.声音源不在墙内就在墙外，考虑许多人根本楼上无人住之类种种情形，且都是相似弹珠声；声音源必在墙内，墙内东西就是水泥、水管、钢筋、电线这四种，热帐冷缩已经排除，那这就是逻辑上唯一解释。
2. 既然多发生在下方钢筋网，所以都是听到从天花板传来，楼上要听到由地上传来可能当时要刚好耳贴近地板，这机率就小多了，因为事实证明厚水泥隔音效果比想象 中强，如果上方刚好放有大家具就更难听到了，且很少人天花板会贴东西，地板却常常贴有瓷砖或木头~更阻隔了声音传导。也许有人打地铺睡觉时运气好才会听到 吧。
3.这又解释了为什么几乎没人听过墙壁传出弹珠，因为隔间墙多半是砖墙根本没钢筋，机率就少太多，就算有；听到什么也会以为隔壁在钉东西。
]]></description>
			<content:encoded><![CDATA[<p class="f14 p90 pl10"> <ca>你是否经常听到楼上有弹珠掉地上的声音？<br />
</ca></p>
<p class="f14 p90 pl10"><ca><br />
近来在互联网上看到，有人在网上做了一个调查，发现有80％的人听到过,每次都是2－3声象弹珠球跌落在地上又弹起的声音&#8230;<br />
每次都是2－4声&#8230;.而且都是在半夜听到，声音好象还挺重的<br />
现在的小朋友还玩弹珠吗？<br />
并且有时还听到麻将骰子掉地的声音！<br />
还有有时也可以听到好象一些家具搬动的声音，仿佛是人在拖一样！</ca></p>
<p>以前还一直疑惑是什么原因，当时也并不怎么在意！没有深究其原因！但是通过互联网以后，发现很多朋友都似乎听到过这种来历不明的声音！！！这就奇怪了，全国各地难道都会出现这样的情形吗？？？这不是特别针对与个人的事情呀？</p>
<p>究竟是什么原因呢？是热膨冷缩吗？</p>
<p>实验一：真的跑去楼上打弹珠，发现声音根本几乎是听不到，其实地板比一般人想象中要厚得很多，顶多像文具、手表之类掉到地上的声音，如果这都听得到~那我看还得了，楼上一举一动你都听得到。</p>
<p>实验证明声音能否传到楼下和那个东西的重量有很大关系，也许这有声学或物理上的原因吧，在此就不探究了，总之就算刻意把弹珠很大力砸在地上~~也要夜深人静又很仔细听才听到一些(而且声音种类也不像)</p>
<p>实验二：一块1*1*0.17公尺的水泥块，内嵌钢筋网和两根水管<br />
在实验室用压克力玻璃罩住里用热空气加热法；加到比室温高50度后持续90分钟，之后罩子打开浇冷水加吹风扇急速冷却，结果&#8230;&#8230;啥事也没发生~什么鬼声也没有.</p>
<p>实验三：同样水泥块同样步骤，这次用半虎钳+铁板把前后左右抵住卡紧；结果&#8230;&#8230;啥事又没发生~边缘有非常非常细的小小裂纹而已~什么鬼声也没有</p>
<p>那么~到底答案是什么??</p>
<p>原来元凶就是霉菌!!</p>
<p>是一种不完全菌纲的霉菌为主会腐蚀工业材料与水泥，好生于多细孔表面，以水泥中矿物质为食。</p>
<p>一般天花板是上下两层的细钢筋作支撑，在灌浆的时候其实钢筋不是笔直的被卡在水泥中，受到水泥浆的流动和重量可能会有向上或向左右的应力累积着，或着房子盖好数年后~受到地震或地基小位移等等因素，细钢筋又会产生新的应力。</p>
<p>在天花板的偏下层有电灯线路的管线出口，有温度与空气等等所以霉菌会沿着该孔开始逐步入侵水泥中缝细，细钢筋与水泥接触面是最理想缝细，霉菌多聚 生于此，菌丝向四周开始侵蚀成一个中空型管道。当某根有应力钢筋的周围水泥被侵蚀到一定程度后便会在中空管道中来回弹动，这就是弹珠声的来源。</p>
<p>所以实验下一步就刻意制作水泥块后；中间夹入比钢筋略粗的塑料棒形成中空道，水泥半干后拿出塑料管插入钢筋，再从另一端灌一些水泥固定。</p>
<p>事实证明，细钢筋在管道中弹动的声音和弹珠声是最像的。</p>
<p>这解释了以下几点</p>
<p>1.声音源不在墙内就在墙外，考虑许多人根本楼上无人住之类种种情形，且都是相似弹珠声；声音源必在墙内，墙内东西就是水泥、水管、钢筋、电线这四种，热帐冷缩已经排除，那这就是逻辑上唯一解释。</p>
<p>2. 既然多发生在下方钢筋网，所以都是听到从天花板传来，楼上要听到由地上传来可能当时要刚好耳贴近地板，这机率就小多了，因为事实证明厚水泥隔音效果比想象 中强，如果上方刚好放有大家具就更难听到了，且很少人天花板会贴东西，地板却常常贴有瓷砖或木头~更阻隔了声音传导。也许有人打地铺睡觉时运气好才会听到 吧。</p>
<p>3.这又解释了为什么几乎没人听过墙壁传出弹珠，因为隔间墙多半是砖墙根本没钢筋，机率就少太多，就算有；听到什么也会以为隔壁在钉东西。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/strange-sound-in-night/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[zt]程序员的温情管理文化</title>
		<link>http://www.hlouis.com/diary/cheng-xu-yuan-guan-li/</link>
		<comments>http://www.hlouis.com/diary/cheng-xu-yuan-guan-li/#comments</comments>
		<pubDate>Thu, 10 Jan 2008 01:39:29 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Diary]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/cheng-xu-yuan-guan-li/</guid>
		<description><![CDATA[作者：virushuo 发表于 2008-01-10 01:01 最后更新于 2008-01-10 01:01
版权声明：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明。
http://blog.devep.net/virushuo/2008/01/10/programmer-warmth-manage.html
 今天戴飞和我聊起来为什么在一些公司会很闲但是很累，在另外一些公司工作量大但是很开心的话题。不由得勾起了我总结一下长久以来关于工作，尤其是对程序员的工作管理的一些话题。从我带第一个技术团队算起，已经有很多年了。我始终坚持的一件事就是温情。所谓温情，很简单，替别人多想一些。我在附中的时候，下班总要“轰”大家回家，不让团队成员加班。如果为了躲避晚高峰不想走，我就鼓动他们玩玩游戏，看看电影看看书，别太累。
这事情在所谓“管理者”眼里是个笑话，在他们那里几个参数是等同的，加班＝＝工资＝＝产能。事实上每个工作过几年的人都知道这不可能。程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。
在这种情况下，我更愿意在质量和工作量中找一个平衡点。即，不让任何一个人累着，不要让他们早晨起来躺在床上懒得上班，不要让他们因为加班被家人抱怨甚至感情危机。人首先是生活的人，如果放弃了生活，工作也没意义。皮之不存，毛将焉附？
最终找到的这种平衡点很有趣。那就是，程序员很难在一天内完成超过4个小时的高效工作。我说的是要求质量，有能动性，要动脑子，有创意的那种工作，拼贴代码那种机械工作咱们就不讨论了。因此我尝试在我和tiny的新公司实行每天6小时，每周30小时工作制。同时我们在力所能及的情况下不主动压低任何人的工资。我们不用期权引诱人，我们首先保证所有人生活正常，无压力，虽然我们认为我们的期权很值钱。但值钱不值钱这件事不是自己吹牛吹出来的，是大家共同努力出来的。
事实证明，每天6个小时工作时间不但没有降低效率，反而比8个小时高很多。想想也不奇怪，早晚放弃了1个小时，所有人都可以躲过早晚交通高峰，路上花费更少的时间，不会被人挤，心情不会太差，到公司可以很快进入工作状态，且心情轻松。
我倾向于相信，如果生活稳定，家庭幸福，收入正常，且在做一份有未来的事业，所有人都愿意尽自己最大努力。反之，其实所有人都有去稳定的大公司的机会。没人愿意来创业。
说到这里，一定会有人反驳：软件工程就是用来降低程序员不稳定性，工作量不够，产品质量不高的问题的。是的，这种说法完全对，不过仅限于外包领域。 外包领域具有明确的需求和验收标准，产品相当稳定。他们追求的是重复性，可复用性。因此他们希望通过一种机制，让程序员变成机器。一个程序员“坏了”（不 开心了，辞职了，老了精力下降了），那就换一个，就好像换掉一个巨大机器上面的齿轮，咔的一声，拧好螺丝，继续运转，一切都跟没发生过一样。刚才那个被拧 下的齿轮呢？老天，谁关心那个。
在互联网，尤其是带有较高技术含量的领域，或是新鲜的领域，我们因为没有标准可循，所以并不需要这种机器。我力图把程序员重新还原成人。所以我更喜 欢创造一个有温情的环境。其实不仅仅我这个小创业者的胡思乱想，google给员工极度的自由，极好的待遇，我觉得也可以看做这种思路。google知道 无法管理技术人员，所以他们干脆选择了彻底的，全面的妥协。一切都交给你们，你们努力去做就好，我们不给你压力。事实上，在选好人的情况下，这种思路产生 的产能是惊人的。当然，在中国似乎没选好人，所以产生的浪费也是惊人的。
几乎所有武术都在讲，出拳的时候手臂要放松，接触目标的瞬间发力，这样才有力量。如果出拳即发力，则会导致肌肉紧张，动作变形，最终你使出了全身的力气，却只打出了软绵绵的一拳。这多么的悲哀。
]]></description>
			<content:encoded><![CDATA[<p>作者：<a href="http://www.devep.net/">virushuo</a> 发表于 2008-01-10 01:01 最后更新于 2008-01-10 01:01<br />
<a href="http://creativecommons.org/licenses/by-sa/2.5/">版权声明</a>：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及<a href="http://www.chedong.com/blog/archives/001249.html">本声明</a>。<br />
<a href="http://blog.devep.net/virushuo/2008/01/10/programmer-warmth-manage.html" class="permalink">http://blog.devep.net/virushuo/2008/01/10/programmer-warmth-manage.html</a></p>
<hr /> 今天<a href="http://blog.donews.com/bonycamel">戴飞</a>和我聊起来为什么在一些公司会很闲但是很累，在另外一些公司工作量大但是很开心的话题。不由得勾起了我总结一下长久以来关于工作，尤其是对程序员的工作管理的一些话题。从我带第一个技术团队算起，已经有很多年了。我始终坚持的一件事就是温情。所谓温情，很简单，替别人多想一些。我在附中的时候，下班总要“轰”大家回家，不让团队成员加班。如果为了躲避晚高峰不想走，我就鼓动他们玩玩游戏，看看电影看看书，别太累。</p>
<p>这事情在所谓“管理者”眼里是个笑话，在他们那里几个参数是等同的，加班＝＝工资＝＝产能。事实上每个工作过几年的人都知道这不可能。程序员是这样 一群家伙，他们可以把1000行代码写成10行，当然也可以把10行代码写成1000行。他们可以让这1000行代码比那10行容易看懂效率更高，也可以 让那10行比这1000行容易看懂效率更高。</p>
<p>在这种情况下，我更愿意在质量和工作量中找一个平衡点。即，不让任何一个人累着，不要让他们早晨起来躺在床上懒得上班，不要让他们因为加班被家人抱怨甚至感情危机。人首先是生活的人，如果放弃了生活，工作也没意义。皮之不存，毛将焉附？</p>
<p>最终找到的这种平衡点很有趣。那就是，程序员很难在一天内完成超过4个小时的高效工作。我说的是要求质量，有能动性，要动脑子，有创意的那种工作，拼贴代码那种机械工作咱们就不讨论了。因此我尝试在我和<a href="http://www.tinydust.net/">tiny</a>的新公司实行每天6小时，每周30小时工作制。同时我们在力所能及的情况下不主动压低任何人的工资。我们不用期权引诱人，我们首先保证所有人生活正常，无压力，虽然我们认为我们的期权很值钱。但值钱不值钱这件事不是自己吹牛吹出来的，是大家共同努力出来的。</p>
<p>事实证明，每天6个小时工作时间不但没有降低效率，反而比8个小时高很多。想想也不奇怪，早晚放弃了1个小时，所有人都可以躲过早晚交通高峰，路上花费更少的时间，不会被人挤，心情不会太差，到公司可以很快进入工作状态，且心情轻松。</p>
<p>我倾向于相信，如果生活稳定，家庭幸福，收入正常，且在做一份有未来的事业，所有人都愿意尽自己最大努力。反之，其实所有人都有去稳定的大公司的机会。没人愿意来创业。</p>
<p>说到这里，一定会有人反驳：软件工程就是用来降低程序员不稳定性，工作量不够，产品质量不高的问题的。是的，这种说法完全对，不过仅限于外包领域。 外包领域具有明确的需求和验收标准，产品相当稳定。他们追求的是重复性，可复用性。因此他们希望通过一种机制，让程序员变成机器。一个程序员“坏了”（不 开心了，辞职了，老了精力下降了），那就换一个，就好像换掉一个巨大机器上面的齿轮，咔的一声，拧好螺丝，继续运转，一切都跟没发生过一样。刚才那个被拧 下的齿轮呢？老天，谁关心那个。</p>
<p>在互联网，尤其是带有较高技术含量的领域，或是新鲜的领域，我们因为没有标准可循，所以并不需要这种机器。我力图把程序员重新还原成人。所以我更喜 欢创造一个有温情的环境。其实不仅仅我这个小创业者的胡思乱想，google给员工极度的自由，极好的待遇，我觉得也可以看做这种思路。google知道 无法管理技术人员，所以他们干脆选择了彻底的，全面的妥协。一切都交给你们，你们努力去做就好，我们不给你压力。事实上，在选好人的情况下，这种思路产生 的产能是惊人的。当然，在中国似乎没选好人，所以产生的浪费也是惊人的。</p>
<p>几乎所有武术都在讲，出拳的时候手臂要放松，接触目标的瞬间发力，这样才有力量。如果出拳即发力，则会导致肌肉紧张，动作变形，最终你使出了全身的力气，却只打出了软绵绵的一拳。这多么的悲哀。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/diary/cheng-xu-yuan-guan-li/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[ZT]MMORPG Server Design</title>
		<link>http://www.hlouis.com/design/ztmmorpg-server-design/</link>
		<comments>http://www.hlouis.com/design/ztmmorpg-server-design/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 02:38:10 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/ztmmorpg-server-design/</guid>
		<description><![CDATA[转载自 http://www.cppblog.com/Fox/archive/2007/12/16/38600.html
这篇文章转载自Fox的研究论文的开题报告，写的比较细致，和我目前所做得工作也比较相似。不过行文的水平比我高，把很多我说不明白的事情都表达了出来。很多具体的问题没还有深入，期待后续的文章



Author: Fox(yulefox@126.com)

一个MMORPG（Massively Multiplayer Online Role Playing Game）的架构包含客户端和服务器两部分。客户端主要涉及计算机图形学、物理学、多媒体技术等，服务器主要涉及网络通信技术、数据库技术，而人工智能、操作系统等计算机基础学科知识的应用体现在MMORPG开发过程中的方方面面。

一、游戏世界的划分
理想状态的游戏世界仅由一个完整的场景组成，在《魔兽争霸III》、《CS》这样的单机游戏中，所有玩家位于该场景中，在理论上，位于该场景中的任意玩家都可以看到游戏中所有玩家并与之交互，出于公平性和游戏性（而不是技术上）的考虑，游戏中并不会这样做。
然而，目前的MMORPG中，几乎没有任何一款可以做到整个游戏世界只包含一个场景，因为在一款MMORPG中，同时在线的玩家数量成百上千，甚至是数万人同时在一个游戏世界中交互。以现在的网络技术和计算机系统，还无法为这么多玩家的交互提供即时处理。因此，MMORPG的游戏世界被划分为大小不等、数量众多的场景，游戏服务器对于这些场景的处理分为分区和无缝两种。
在分区式服务器中，一个场景中的玩家无法看到另一个场景中的玩家，当玩家从一个场景到另外一个场景跨越时，都有一个数据转移和加载的过 程（尤其是从一个分区服务器跨越到另外一个服务器时），玩家都有一个等待的时间，在这段时间内，服务器的主要工作是实现跨越玩家数据的转移和加载以及后一 个场景中玩家、NPC等数据的传输，客户端的主要工作是实现新场景资源的加载和服务器通信。主要时 间的长短主要取决于后一个场景中资源数据的大小。分区式服务器的优点主要是各分区服务器保持相对独立，缺点是游戏空间不够大，而且，一旦某个分区服务器中 止服务，位于该服务器上的所有玩家将失去连接。
所谓无缝服务器，玩家几乎察觉不到场景之间的这种切换，在场景间没有物理上的屏障，对于玩家而言，众多场景构成了一个巨大的游戏世界。 场景之间，甚至服务器之间“没有了”明确的界线。因此，无缝服务器为玩家提供了更大的游戏空间和更友好的交互，实现了动态边界的无缝服务器甚至可以在某个 服务器中止服务时，按一定策略将负载动态分散到其他服务器。因此，无缝服务器在技术上要比分区服务器更加复杂。
目前国内上市的MMORPG，大多采用分区式服务器，做到无缝世界的主要有《完美世界》和《天下贰》等，国外的MMORPG中，像《魔兽世界》、《EVE》等，都实现了无缝世界。
无缝服务器与分区式服务器在技术上的主要区别是，当位于场景S1中的玩家P1处于两个（甚至更多）场景S1、S2的边界区域内时，要保证P1能够看到场景S2中建筑、玩家、NPC等可感知对象。而且边界区域的大小要大于等于P1可感知的范围，否则就可能发生S2中的可感知对象突然闪现在P1视野中的异常。
无疑，无缝世界为玩家提供了更人性化和更具魅力的用户体验。
二、无缝世界游戏服务器的整体架构
MMORPG的服务器架构从功能上主要划分为三种：
1、登录服务器（Login Server）
登录服务器用于玩家验证登录，并根据系统记录玩家信息得到其所在节点服务器，并通过世界服务器为登录玩家和对应节点服务器建立连接。
2、世界服务器（World Server）
世界服务器将整个游戏世界划分成不同场景，将所有场景按一定策略分配给节点服务器，并对节点服务器进行管理。世界服务器的另一功能是与 登录服务器交互。因此，世界服务器是登录服务器、节点服务器的沟通桥梁，当然，一旦玩家登录成功，世界服务器将主要处理节点服务器间的通信。因此，世界服 务器对于玩家是透明的。
3、节点服务器（Node Server）
节点服务器负责管理位于该节点的所有玩家、NPC的所有交互，在无缝世界游戏中，由于边界区域的存在，一个节点服务器甚至要处理相邻节点上位于边界区域的玩家和NPC的信息。
在具体实现上，不同的MMORPG为了便于管理，可能还会具有AI服务器、日志服务器、数据库缓存服务器、代理服务器等。
三、无缝世界游戏服务器的主要技术需求
1、编程语言（C/C++、SQL、Lua、Python）
2、图形库（Direct 3D、OpenGL）
3、网络通信（WinSock、BSD Socket，或者ACE）
4、消息、事件、多线程、GUI
5、OS
三、无缝世界游戏服务器需要解决的主要问题
1、资源管理
无论是服务器还是客户端，都涉及到大量资源：玩家数据、NPC数据、战斗公式、模型资源、通信资源等。当这些资源达到一定规模，其管理的难度不可忽视。而且，资源管理的好坏，直接关系到游戏的安全和生命。
2、网络安全
安全永远是第一位的，我们无法指望所有的玩家及其所持的客户端永远是友好的。事实上，威胁到游戏的公平性和安全性的大多数问题，归根结底，都是由于网络通信中存在的欺骗和攻击造成的，这些问题包含但不限于交易欺骗、物品复制。
3、逻辑安全
逻辑安全按理说应该是游戏中最基本的考虑，覆盖的范围也最广最杂。随机数系统是一个非常值得重视的问题，随机数不仅仅用于玩家可见的一 些任务系统、战斗公式、人工智能、物品得失等，还可用于网络报文加密等。因此，随机数系统本身的安全不容忽视。另外一个常见的逻辑安全是玩家的移动，最主 要的就是防止加速齿轮这样的变态操作。
4、负载均衡
MMORPG中的负载均衡包括客户端及服务器资源管理和逻辑处理的负载均衡，其中最难预知的是网络通信的负 载均衡，正常情况下的网络通信数量是可以在游戏设计时做出评估的，但因恶意攻击造成的网络负载是无法预测的。因此，负载均衡所要处理的主要是实时动态负载 均衡和灾难恢复。负载均衡需要解决的问题包括负载监控、负载分析、负载分发和灾难恢复。
5、录像系统
录像系统的构建，主要用于重现关键数据的输入输出，如玩家交易、玩家充值，或者当bug出现后，为逻辑服务器（泛指上文提到的所有类型服务器，主要是节点服务器）相应部分启动录像系统。待收集到足够数据后，通过录像系统重现bug。为了使逻辑服务器不受自身时间（如中断调试等）的影响，还可以专门设计心跳服务器来控制数据传输。
四、总结
在MMORPG中，真正的bug永远存在于将来。从这一点出发，关于MMORPG中游戏世界的构建，怎样苛刻的思考都不为过。
参考资料：
1、 [美] Kim Pallister编, 孟宪武 等译. 游戏编程精粹5, P467-474, P516. 人民邮电出版社, 2007年9月. 北京.
2、 [美] Thor Alexander编, 史晓明 译. 大型多人在线游戏开发, P174-185. 人民邮电出版社, 2006年12月. 北京.
3、 [美] Dante Treglia编, 张磊 译. 游戏编程精粹3, P117-122. 人民邮电出版社, 2003年7月. [...]]]></description>
			<content:encoded><![CDATA[<p>转载自 <a href="http://www.cppblog.com/Fox/archive/2007/12/16/38600.html">http://www.cppblog.com/Fox/archive/2007/12/16/38600.html</a></p>
<p>这篇文章转载自Fox的研究论文的开题报告，写的比较细致，和我目前所做得工作也比较相似。不过行文的水平比我高，把很多我说不明白的事情都表达了出来。很多具体的问题没还有深入，期待后续的文章</p>
<p></p>
<hr />
</p>
<p>Author: Fox(<a href="mailto:yulefox@126.com" target="_blank">yulefox@126.com</a>)<br />
<span><br />
一个</span><span>MMORPG</span><span>（</span><span>Massively Multiplayer Online Role Playing Game</span><span>）的架构包含客户端和服务器两部分。客户端主要涉及计算机图形学、物理学、多媒体技术等，服务器主要涉及网络通信技术、数据库技术，而人工智能、操作系统等计算机基础学科知识的应用体现在</span><span>MMORPG</span><span>开发过程中的方方面面。</span></p>
<p><span id="more-74"></span></p>
<p><span>一、游戏世界的划分</span></p>
<p><span>理想状态的游戏世界仅由一个完整的场景组成，在《魔兽争霸</span><span>III</span><span>》、《</span><span>CS</span><span>》这样的单机游戏中，所有玩家位于该场景中，在理论上，位于该场景中的任意玩家都可以看到游戏中所有玩家并与之交互，出于公平性和游戏性（而不是技术上）的考虑，游戏中并不会这样做。</span></p>
<p><span>然而，目前的</span><span>MMORPG</span><span>中，几乎没有任何一款可以做到整个游戏世界只包含一个场景，因为在一款</span><span>MMORPG</span><span>中，同时在线的玩家数量成百上千，甚至是数万人同时在一个游戏世界中交互。以现在的网络技术和计算机系统，还无法为这么多玩家的交互提供即时处理。因此，</span><span>MMORPG</span><span>的游戏世界被划分为大小不等、数量众多的场景，游戏服务器对于这些场景的处理分为分区和无缝两种。</span></p>
<p><span>在分区式服务器中，一个场景中的玩家无法看到另一个场景中的玩家，当玩家从一个场景到另外一个场景跨越时，都有一个数据转移和加载的过 程（尤其是从一个分区服务器跨越到另外一个服务器时），玩家都有一个等待的时间，在这段时间内，服务器的主要工作是实现跨越玩家数据的转移和加载以及后一 个场景中玩家、</span><span>NPC</span><span>等数据的传输，客户端的主要工作是实现新场景资源的加载和服务器通信。主要时 间的长短主要取决于后一个场景中资源数据的大小。分区式服务器的优点主要是各分区服务器保持相对独立，缺点是游戏空间不够大，而且，一旦某个分区服务器中 止服务，位于该服务器上的所有玩家将失去连接。</span></p>
<p><span>所谓无缝服务器，玩家几乎察觉不到场景之间的这种切换，在场景间没有物理上的屏障，对于玩家而言，众多场景构成了一个巨大的游戏世界。 场景之间，甚至服务器之间“没有了”明确的界线。因此，无缝服务器为玩家提供了更大的游戏空间和更友好的交互，实现了动态边界的无缝服务器甚至可以在某个 服务器中止服务时，按一定策略将负载动态分散到其他服务器。因此，无缝服务器在技术上要比分区服务器更加复杂。</span></p>
<p><span>目前国内上市的</span><span>MMORPG</span><span>，大多采用分区式服务器，做到无缝世界的主要有《完美世界》和《天下贰》等，国外的</span><span>MMORPG</span><span>中，像《魔兽世界》、《</span><span>EVE</span><span>》等，都实现了无缝世界。</span></p>
<p><span>无缝服务器与分区式服务器在技术上的主要区别是，当位于场景</span><span>S1</span><span>中的玩家</span><span>P1</span><span>处于两个（甚至更多）场景</span><span>S1</span><span>、</span><span>S2</span><span>的边界区域内时，要保证</span><span>P1</span><span>能够看到场景</span><span>S2</span><span>中建筑、玩家、</span><span>NPC</span><span>等可感知对象。而且边界区域的大小要大于等于</span><span>P1</span><span>可感知的范围，否则就可能发生</span><span>S2</span><span>中的可感知对象突然闪现在</span><span>P1</span><span>视野中的异常。</span></p>
<p><span>无疑，无缝世界为玩家提供了更人性化和更具魅力的用户体验。</span></p>
<p><span>二、无缝世界游戏服务器的整体架构</span></p>
<p><span>MMORPG</span><span>的服务器架构从功能上主要划分为三种：</span></p>
<p><span><span>1、</span></span><span>登录服务器（</span><span>Login Server</span><span>）</span></p>
<p><span>登录服务器用于玩家验证登录，并根据系统记录玩家信息得到其所在节点服务器，并通过世界服务器为登录玩家和对应节点服务器建立连接。</span></p>
<p><span><span>2、</span></span><span>世界服务器（</span><span>World Server</span><span>）</span></p>
<p><span>世界服务器将整个游戏世界划分成不同场景，将所有场景按一定策略分配给节点服务器，并对节点服务器进行管理。世界服务器的另一功能是与 登录服务器交互。因此，世界服务器是登录服务器、节点服务器的沟通桥梁，当然，一旦玩家登录成功，世界服务器将主要处理节点服务器间的通信。因此，世界服 务器对于玩家是透明的。</span></p>
<p><span><span>3、</span></span><span>节点服务器（</span><span>Node Server</span><span>）</span></p>
<p><span>节点服务器负责管理位于该节点的所有玩家、</span><span>NPC</span><span>的所有交互，在无缝世界游戏中，由于边界区域的存在，一个节点服务器甚至要处理相邻节点上位于边界区域的玩家和</span><span>NPC</span><span>的信息。</span></p>
<p><span>在具体实现上，不同的</span><span>MMORPG</span><span>为了便于管理，可能还会具有</span><span>AI</span><span>服务器、日志服务器、数据库缓存服务器、代理服务器等。</span></p>
<p><span><span>三、</span></span><span>无缝世界游戏服务器的主要技术需求</span></p>
<p><span><span>1、</span></span><span>编程语言（</span><span>C/C++</span><span>、</span><span>SQL</span><span>、</span><span>Lua</span><span>、</span><span>Python</span><span>）</span></p>
<p><span><span>2、</span></span><span>图形库（</span><span>Direct 3D</span><span>、</span><span>OpenGL</span><span>）</span></p>
<p><span><span>3、</span></span><span>网络通信（</span><span>WinSock</span><span>、</span><span>BSD Socket</span><span>，或者</span><span>ACE</span><span>）</span></p>
<p><span><span>4、</span></span><span>消息、事件、多线程、</span><span>GUI</span></p>
<p><span><span>5、</span></span><span>OS</span></p>
<p><span>三、无缝世界游戏服务器需要解决的主要问题</span></p>
<p><span><span>1、</span></span><span>资源管理</span></p>
<p><span>无论是服务器还是客户端，都涉及到大量资源：玩家数据、</span><span>NPC</span><span>数据、战斗公式、模型资源、通信资源等。当这些资源达到一定规模，其管理的难度不可忽视。而且，资源管理的好坏，直接关系到游戏的安全和生命。</span></p>
<p><span><span>2、</span></span><span>网络安全</span></p>
<p><span>安全永远是第一位的，我们无法指望所有的玩家及其所持的客户端永远是友好的。事实上，威胁到游戏的公平性和安全性的大多数问题，归根结底，都是由于网络通信中存在的欺骗和攻击造成的，这些问题包含但不限于交易欺骗、物品复制。</span></p>
<p><span><span>3、</span></span><span>逻辑安全</span></p>
<p><span>逻辑安全按理说应该是游戏中最基本的考虑，覆盖的范围也最广最杂。随机数系统是一个非常值得重视的问题，随机数不仅仅用于玩家可见的一 些任务系统、战斗公式、人工智能、物品得失等，还可用于网络报文加密等。因此，随机数系统本身的安全不容忽视。另外一个常见的逻辑安全是玩家的移动，最主 要的就是防止加速齿轮这样的变态操作。</span></p>
<p><span><span>4、</span></span><span>负载均衡</span></p>
<p><span>MMORPG</span><span>中的负载均衡包括客户端及服务器资源管理和逻辑处理的负载均衡，其中最难预知的是网络通信的负 载均衡，正常情况下的网络通信数量是可以在游戏设计时做出评估的，但因恶意攻击造成的网络负载是无法预测的。因此，负载均衡所要处理的主要是实时动态负载 均衡和灾难恢复。负载均衡需要解决的问题包括负载监控、负载分析、负载分发和灾难恢复。</span></p>
<p><span><span>5、</span></span><span>录像系统</span></p>
<p><span>录像系统的构建，主要用于重现关键数据的输入输出，如玩家交易、玩家充值，或者当</span><span>bug</span><span>出现后，为逻辑服务器（泛指上文提到的所有类型服务器，主要是节点服务器）相应部分启动录像系统。待收集到足够数据后，通过录像系统重现</span><span>bug</span><span>。为了使逻辑服务器不受自身时间（如中断调试等）的影响，还可以专门设计心跳服务器来控制数据传输。</span></p>
<p><span>四、总结</span></p>
<p><span>在</span><span>MMORPG</span><span>中，真正的</span><span>bug</span><span>永远存在于将来。从这一点出发，关于</span><span>MMORPG</span><span>中游戏世界的构建，怎样苛刻的思考都不为过。</span></p>
<p>参考资料：</p>
<p><span>1、 [美] Kim Pallister编, 孟宪武 等译. 游戏编程精粹5, P467-474, P516. 人民邮电出版社, 2007年9月. 北京.<br />
2、 [美] Thor Alexander编, 史晓明 译. 大型多人在线游戏开发, P174-185. 人民邮电出版社, 2006年12月. 北京.<br />
3、 [美] Dante Treglia编, 张磊 译. 游戏编程精粹3, P117-122. 人民邮电出版社, 2003年7月. 北京.<br />
4、 [美] Mark DeLoura编, 王淑礼 等译. 游戏编程精粹1, P90-93. 人民邮电出版社, 2004年10月. 北京.<br />
5、 [美] Douglas 等著, 於春景 译. C++网络编程 卷1. 中国电力出版社, 2004年11月. 北京.<br />
6、 [美] Stephen D. Huston 等著, 马维达 译. ACE程序员指南. 中国电力出版社, 2004年11月. 北京.<br />
7、 [美] Erich Gamma等著, 李英军 等译. 设计模式. 机械工业出版社, 2000年6月. 北京.<br />
8、 游戏引擎全剖析. <a href="http://bbs.gameres.com/showthread.asp?threadid=101293" target="_blank">http://bbs.gameres.com/showthread.asp?threadid=101293</a>.<br />
9、 服务器结构探讨：登录服的负载均衡. <a href="http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3" target="_blank">http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3</a>.<br />
10、服务器结构探讨：最终的结构. <a href="http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3" target="_blank">http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3</a>.<br />
11、谈谈网络游戏服务器解决方案. <a href="http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm" target="_blank">http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm</a>.<br />
12、负载均衡——大型在线系统实现的关键(下篇)（服务器集群架构的设计与选择）. <a href="http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx" target="_blank">http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx</a>.<br />
13、云风的BLOG. <a href="http://blog.codingnow.com/" target="_blank">http://blog.codingnow.com/</a><br />
</span></p>
<p><span style="color: #008000">/*****************************************************************************<br />
从0:00到5:00，在写这篇随笔的过程中，我翻找、点击着上面的这些资料，其实还有更<br />
多的资料，没有记在上面，算是为开题做的准备。现在依然是睡意全无。越写越觉得<br />
不够，越想越觉得还有更多东西写不出来……<br />
PS：这些资料大都不是第一次翻，以前看这些资料大多只是单纯的看，现在有目的的<br />
看，才觉得都写得很有味道。不管是不是同意所有观点，都不是本文讨论的重点。<br />
*****************************************************************************/</span>  <img src="http://www.cppblog.com/Fox/aggbug/38600.html" height="1" width="1" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/ztmmorpg-server-design/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flex SecurityError 2148</title>
		<link>http://www.hlouis.com/develop/flash-window/flex-securityerror-2148/</link>
		<comments>http://www.hlouis.com/develop/flash-window/flex-securityerror-2148/#comments</comments>
		<pubDate>Sat, 08 Dec 2007 12:12:42 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Flash window]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/develop/flash-window/flex-securityerror-2148/</guid>
		<description><![CDATA[Flex SecurityError: Error #2148 While Accessing local XML
So you’ve published your Flex application that accesses local XML, but when you try to run it outside of your Flex Builder folder, you might get a Flash Player Debugger error #2148. I ran into this problem while on a tight deadline, and am reposting here to get [...]]]></description>
			<content:encoded><![CDATA[<h2><a href="http://blog.mandalatv.net/?p=334" rel="bookmark" title="Permanent Link: Flex SecurityError: Error #2148 While Accessing local XML">Flex SecurityError: Error #2148 While Accessing local XML</a></h2>
<p>So you’ve published your Flex application that accesses local XML, but when you try to run it outside of your Flex Builder folder, you might get a Flash Player Debugger error #2148. I ran into this problem while on a tight deadline, and am reposting here to get the word out.</p>
<p>To fix this, you need:</p>
<ol>
<li>to right/control click your Flex Project folder in the Navigator</li>
<li>Select properties</li>
<li>Choose Flex Compiler in the popup window</li>
<li>Add “-use-network=false” under Additional compiler arguments</li>
</ol>
<p><img src="http://blog.mandalatv.net/wp-content/uploads/2007/06/flexproperties.jpg" alt="flexproperties.jpg" id="image333" /></p>
<p>Hopefully, this’ll save someone some time…</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/flash-window/flex-securityerror-2148/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Expose inside design</title>
		<link>http://www.hlouis.com/design/expose-inside-design/</link>
		<comments>http://www.hlouis.com/design/expose-inside-design/#comments</comments>
		<pubDate>Thu, 06 Dec 2007 07:56:59 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/expose-inside-design/</guid>
		<description><![CDATA[有些时候，UI的一个设计准则就是将程序内部的设计结构暴露出来给用户，比如Mac系统上很流行的一个tap-to-run的程序，Quicksilver，一个基于键盘的程序启动软件，它的基本界面如下：

如上所见，左边是Quicksilver根据我让键入的字符在系统中寻找到的对象，右边就是针对这个对象所做的动作，用户可以使用默认动作或者是使用其他的动作。例如针对一个文本文件就有预览，打开等动作。
没有看过Quicksilver的代码，不过相信要我做一个这样的类似程序，我也一定会做这样的内部设计：
对象 &#8212; 动作
将对象和动作分别封装成两种最基础的类型，让他们之间有一定的属性可以互相交互从而形成关联。对于程序设计者来说，这个可能是最基础的想法。Quicksilver也忠实的将这个想法反应到UI上。程序设计师对于软件的理解肯定要比一般的使用者深入，如果我们能将一个好的设计暴露到UI上，往往可以给普通用户带来更好的体验。
]]></description>
			<content:encoded><![CDATA[<p>有些时候，UI的一个设计准则就是将程序内部的设计结构暴露出来给用户，比如Mac系统上很流行的一个tap-to-run的程序，Quicksilver，一个基于键盘的程序启动软件，它的基本界面如下：</p>
<p><img src="http://www.hlouis.com/hlouis_com/wp-content/uploads/2007/12/0_quicksilver001.jpg" alt="Quicksilver" /></p>
<p>如上所见，左边是Quicksilver根据我让键入的字符在系统中寻找到的对象，右边就是针对这个对象所做的动作，用户可以使用默认动作或者是使用其他的动作。例如针对一个文本文件就有预览，打开等动作。</p>
<p>没有看过Quicksilver的代码，不过相信要我做一个这样的类似程序，我也一定会做这样的内部设计：</p>
<blockquote><p>对象 &#8212; 动作</p></blockquote>
<p>将对象和动作分别封装成两种最基础的类型，让他们之间有一定的属性可以互相交互从而形成关联。对于程序设计者来说，这个可能是最基础的想法。Quicksilver也忠实的将这个想法反应到UI上。程序设计师对于软件的理解肯定要比一般的使用者深入，如果我们能将一个好的设计暴露到UI上，往往可以给普通用户带来更好的体验。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/expose-inside-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Game data server draft design</title>
		<link>http://www.hlouis.com/design/game-data-server-draft-design/</link>
		<comments>http://www.hlouis.com/design/game-data-server-draft-design/#comments</comments>
		<pubDate>Mon, 26 Nov 2007 13:22:14 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/design/game-data-server-draft-design/</guid>
		<description><![CDATA[游戏数据服务器是什么
数据服务器，一下简称DS，用来保存游戏中的数据，他存在与持久层之上，逻辑层之下，是一个针对逻辑层的数据持久层。
为什么需要这层
在我开发游戏服务器以来，发现的一个最严重的问题就是，游戏数据的安全和正确。对于游戏的数据我们大体可以分出一下两类：

临时数据：由游戏运行时生成，无需进行保存。在玩家下线或游戏服务器关闭之后就可以抛弃。
持久数据：游戏人物的数据、游戏中的物品，人物排名等等由玩家或服务器创造出的并有保存价值的数据

对于一款网络游戏来说，数据基本上是一切。玩家丢了数据等于是被盗号，运营商如果丢了很多玩家的数据基本上就无法正常的运营下去。对于数据可能出现的问题如下：

数据回档：档的原因多种多样， 大体有以下的原因：

服务器崩溃导致距离上次存档的数据没有保存
人物数据错乱，导致游戏无法将该玩家的数据保存（和数据库中的某些限制出现冲突）


数据存储效率低下，导致玩家存储数据的时间长于每次存储的间隙
游戏中的物品产生复制，在游戏中的交易的双方交易后出现某一方的回档，物品就会出现复制
数据保存复杂、危险，由于程序员的大量开发工作主要针对于服务器的逻辑，如果需要兼顾撰写保存数据的SQL，很可能出现问题

针对游戏服务器的数据的重要性和易错性，我觉得非常需要添加一层数据层，使游戏数据库对游戏服务器的逻辑透明，同时提供一些简单的方法保证数据的一致性。
具体要求
针对以上的分析，我觉得一个合格的DS需要做到一下的条目：

使SQL对使用者透明：
在这里我们假设，数据库的最终保存持久层依然是某种数据库，那么DS因该可以使用定义的数据类型自动生成保存，更新和读取的SQL语言。撰写逻辑的程序员，只需要定义数据类型和结构，完全不需要考虑和数据库的操作。数据库对于游戏逻辑程序员来说是完全透明的。
数据需要有权限概念：
第一个对某个数据进行访问的用户（其他的游戏逻辑服务器）是该数据的拥有者，拥有者可以限制其他访问者对该数据的权限，是否可读，是否可写等。同时拥有权可以放弃或移交。
支持对数据的原子操作：
对于交易等数据操作，可能需要同时更新两个以上的数据单元，这时候需要提供原子操作的支持，如果某个数据单元的更新不成功，就要让整个操作回滚。
DS本身的稳定以及自我恢复：
DS本身的逻辑应该足够简单，并保证服务稳定，内存占用合理并可以在配置文件中调整。DS如果发现持久层出现错误，比如无法连接到数据库，可以通知客户终止操作，并将当前DS内存的数据dump到本地文件，等待问题修正后可以重新Load到内存中。
多个DS的分布处理：
由于DS的内存和效率等的限制，对于一个游戏应用来说，一个DS可能无法承担所有的应用，需要考虑DS的分布处理。分布处理可能会涉及到很多细节，导致复杂度大大增加，希望有时间，我可以继续讨论这个问题。

]]></description>
			<content:encoded><![CDATA[<h2>游戏数据服务器是什么</h2>
<p>数据服务器，一下简称DS，用来保存游戏中的数据，他存在与持久层之上，逻辑层之下，是一个针对逻辑层的数据持久层。</p>
<h2>为什么需要这层</h2>
<p>在我开发游戏服务器以来，发现的一个最严重的问题就是，游戏数据的安全和正确。对于游戏的数据我们大体可以分出一下两类：</p>
<ul>
<li>临时数据：由游戏运行时生成，无需进行保存。在玩家下线或游戏服务器关闭之后就可以抛弃。</li>
<li>持久数据：游戏人物的数据、游戏中的物品，人物排名等等由玩家或服务器创造出的并有保存价值的数据</li>
</ul>
<p>对于一款网络游戏来说，数据基本上是一切。玩家丢了数据等于是被盗号，运营商如果丢了很多玩家的数据基本上就无法正常的运营下去。对于数据可能出现的问题如下：</p>
<ol>
<li>数据回档：档的原因多种多样， 大体有以下的原因：
<ol>
<li>服务器崩溃导致距离上次存档的数据没有保存</li>
<li>人物数据错乱，导致游戏无法将该玩家的数据保存（和数据库中的某些限制出现冲突）</li>
</ol>
</li>
<li>数据存储效率低下，导致玩家存储数据的时间长于每次存储的间隙</li>
<li>游戏中的物品产生复制，在游戏中的交易的双方交易后出现某一方的回档，物品就会出现复制</li>
<li>数据保存复杂、危险，由于程序员的大量开发工作主要针对于服务器的逻辑，如果需要兼顾撰写保存数据的SQL，很可能出现问题</li>
</ol>
<p>针对游戏服务器的数据的重要性和易错性，我觉得非常需要添加一层数据层，使游戏数据库对游戏服务器的逻辑透明，同时提供一些简单的方法保证数据的一致性。</p>
<h2>具体要求</h2>
<p>针对以上的分析，我觉得一个合格的DS需要做到一下的条目：</p>
<ul>
<li>使SQL对使用者透明：<br />
在这里我们假设，数据库的最终保存持久层依然是某种数据库，那么DS因该可以使用定义的数据类型自动生成保存，更新和读取的SQL语言。撰写逻辑的程序员，只需要定义数据类型和结构，完全不需要考虑和数据库的操作。数据库对于游戏逻辑程序员来说是完全透明的。</li>
<li>数据需要有权限概念：<br />
第一个对某个数据进行访问的用户（其他的游戏逻辑服务器）是该数据的拥有者，拥有者可以限制其他访问者对该数据的权限，是否可读，是否可写等。同时拥有权可以放弃或移交。</li>
<li>支持对数据的原子操作：<br />
对于交易等数据操作，可能需要同时更新两个以上的数据单元，这时候需要提供原子操作的支持，如果某个数据单元的更新不成功，就要让整个操作回滚。</li>
<li>DS本身的稳定以及自我恢复：<br />
DS本身的逻辑应该足够简单，并保证服务稳定，内存占用合理并可以在配置文件中调整。DS如果发现持久层出现错误，比如无法连接到数据库，可以通知客户终止操作，并将当前DS内存的数据dump到本地文件，等待问题修正后可以重新Load到内存中。</li>
<li>多个DS的分布处理：<br />
由于DS的内存和效率等的限制，对于一个游戏应用来说，一个DS可能无法承担所有的应用，需要考虑DS的分布处理。分布处理可能会涉及到很多细节，导致复杂度大大增加，希望有时间，我可以继续讨论这个问题。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/design/game-data-server-draft-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Iptables: How-to Share your internet connection</title>
		<link>http://www.hlouis.com/develop/linux/iptables-how-to-share-your-internet-connection/</link>
		<comments>http://www.hlouis.com/develop/linux/iptables-how-to-share-your-internet-connection/#comments</comments>
		<pubDate>Tue, 20 Nov 2007 02:49:55 +0000</pubDate>
		<dc:creator>Louis</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.hlouis.com/diary/iptables-how-to-share-your-internet-connection/</guid>
		<description><![CDATA[from  http://www.debuntu.org/iptables-how-to-share-your-internet-connection

   
iptables is a command line tool which allow system administrators to configure Linux packet filtering ruleset.
Using iptables, you are able to tweak packet filtering, Network Address Translation (NAT) and packet mangling which in the end are going to allow you to secure your server, share your Internet connection and log [...]]]></description>
			<content:encoded><![CDATA[<p>from  http://www.debuntu.org/iptables-how-to-share-your-internet-connection<!-- google_ad_section_start --></p>
<p class="ad-auto-inserted" style="margin: 0pt 1em 0.25em 0pt; float: left"><!--adsense: cached--></p>
<p class="adsense"> <script type="text/javascript"><!-- google_alternate_ad_url = "http://www.debuntu.org/altadd/rectangle-300.php"; google_ad_client = "pub-3316878663386307"; google_ad_type = "text_image"; google_ad_channel = "8357962815"; google_ad_width = 336; google_ad_height = 280; google_ad_format = "336x280_as"; google_color_border = "ffffff"; google_color_bg = "FAFCFF"; google_color_link = "0A8FBC"; google_color_url = "008000"; google_color_text = "000000"; //--></script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script></p>
<p><strong><a href="http://netfilter.org/" title="iptables" target="_">iptables</a></strong> is a command line tool which allow system administrators to configure Linux packet filtering ruleset.</p>
<p>Using <strong>iptables</strong>, you are able to tweak <em>packet filtering</em>, <em>Network Address Translation</em> (NAT) and <em>packet mangling</em> which in the end are going to allow you to secure your server, share your Internet connection and log unwanted traffic.</p>
<p><strong>iptables</strong> is not really what we could call an easy to get with tool, but once you know the basis, it won&#8217;t be that scary <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>This tutorial will provide a sample script you can use to share your Internet access and will give an overview on how to use <strong>iptables</strong></p>
<h2>1. Introduction</h2>
<p>Most people will be freaked out when you pronounce the name <strong>iptables</strong> because it is not much of an easy to understand software, man page is huge as well as <strong>iptables</strong> capabilities.<br />
To be able to set up a home router, you don&#8217;t actually need to spend nights and nights going through iptables man page, a grasp of the basis is enough to get your firewall up and running.</p>
<p>This tutorial provides a sample script you should be able to use out of the box or at most, changing 2 parameters will be able to get you running.</p>
<h2>2. Iptables</h2>
<p>To be able to understand what the firewall do, there is some basis you need to know. Here I&#8217;m going to go over what make <strong>iptables</strong> handle network packets.</p>
<h3>2.1. Chain Rules</h3>
<p><strong>Iptables</strong> use a set of <em>chain rules</em> to check weather or not a packet should be accepted. By default, there is 3 chains:</p>
<ul>
<li><strong>INPUT</strong>: packet is destinate to the machine running iptables</li>
<li><strong>FORWARD</strong>: packet needs to be forwarded to another machine</li>
<li><strong>OUTPUT</strong>: packet going out of the machine running iptables</li>
</ul>
<p>So when a packet reaches the firewall, the first thing the kernel is going to do is to determine where the packet is going. According to the destination, the kernel will check the packet against the rules of the appropriate chain.</p>
<h3>2.2. Actions (TARGET)</h3>
<p>For each <em>chain</em> we define a list of <em>rules</em> and <em>actions</em> (called <em>targets</em> in iptables&#8217;jargon) to take when a packet match a rule. Main actions are:</p>
<ul>
<li><strong>ACCEPT</strong>: accept the packet <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li><strong>REJECT</strong>: discard the packet and inform the source</li>
<li><strong>DROP</strong>: discard the packet but don&#8217;t say anything to the source</li>
</ul>
<p>As soon as a packet has matched a rule, the kernel will apply the action it is said to do and won&#8217;t go further. If the packet did not match any rules, the kernel will use the <span class="tech">default policy</span> defined for that chain.</p>
<p>This beeing said, we can now get into the script.</p>
<p><span id="more-66"></span></p>
<h2>3. Iptables Script</h2>
<p>OK, now that we know the really basis, let see what the script is going to look like.</p>
<p>In this example, I assume that <em>eth0</em> is the interface connected to the Internet, <em>eth1</em> is the one connected to our local network.</p>
<blockquote>
<pre class="file">#!/bin/sh
#
# this script requires iptables package to be
# installed on your machine

# Where to find iptables binary
IPT="/sbin/iptables"

# The network interface you will use
# WAN is the one connected to the internet
# LAN the one connected to your local network
WAN="eth0"
LAN="eth1"
# First we need to clear up any existing firewall rules
# and chain which might have been created
$IPT -F
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD
$IPT -F -t mangle
$IPT -F -t nat
$IPT -X

# Default policies: Drop any incoming packets
# accept the rest.
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT

# To be able to forward traffic from your LAN
# to the Internet, we need to tell the kernel
# to allow ip forwarding
echo 1 &gt; /proc/sys/net/ipv4/ip_forward

# Masquerading will make machines from the LAN
# look like if they were the router
$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE

# If you want to allow traffic to specific port to be
# forwarded to a machine from your LAN
# here we forward traffic to an HTTP server to machine 192.168.0.2
#$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 80 -j DNAT --to 192.168.0.2:80
#$IPT -A FORWARD -i $WAN -p tcp  --dport 80 -m state --state NEW -j ACCEPT
# For a whole range of port, use:
#$IPT -t nat -A PREROUTING -i $WAN -p tcp --dport 1200:1300 -j DNAT --to 192.168.0.2
#$IPT -A FORWARD -i $WAN -p tcp  --dport 1200:1300 -m state --state NEW -j ACCEPT

# Do not allow new or invalid connections to reach your internal network
$IPT -A FORWARD -i $WAN -m state --state NEW,INVALID -j DROP

# Accept any connections from the local machine
$IPT -A INPUT -i lo -j ACCEPT
# plus from your local network
$IPT -A INPUT -i $LAN -j ACCEPT

# Here we define a new chain which is going to handle
# packets we don't want to respond to
# limit the amount of logs to 10/min
$IPT -N Firewall
$IPT -A Firewall -m limit --limit 10/minute -j LOG --log-prefix "Firewall: "
$IPT -A Firewall -j DROP

# log those packets and inform the sender that the packet was rejected
$IPT -N Rejectwall
$IPT -A Rejectwall -m limit --limit 10/minute -j LOG --log-prefix "Rejectwall: "
$IPT -A Rejectwall -j REJECT
# use the following instead if you want to simulate that the host is not reachable
# for fun though
#$IPT -A Rejectwall -j REJECT  --reject-with icmp-host-unreachable

# here we create a chain to deal with unlegitimate packets
# and limit the number of alerts to 10/min
# packets will be drop without informing the sender
$IPT -N Badflags
$IPT -A Badflags -m limit --limit 10/minute -j LOG --log-prefix "Badflags: "
$IPT -A Badflags -j DROP

# A list of well known combination of Bad TCP flags
# we redirect those to the Badflags chain
# which is going to handle them (log and drop)
$IPT -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ACK,URG URG -j Badflags
$IPT -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j Badflags
$IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j Badflags
$IPT -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ALL ALL -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j Badflags
$IPT -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j Badflags

# Accept certain icmp message, drop the others
# and log them through the Firewall chain
# 0 =&gt; echo reply
$IPT -A INPUT -p icmp --icmp-type 0 -j ACCEPT
# 3 =&gt; Destination Unreachable
$IPT -A INPUT -p icmp --icmp-type 3 -j ACCEPT
# 11 =&gt; Time Exceeded
$IPT -A INPUT -p icmp --icmp-type 11 -j ACCEPT
# 8 =&gt; Echo
# avoid ping flood
$IPT -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT
$IPT -A INPUT -p icmp -j Firewall

# Accept ssh connections from the Internet
$IPT -A INPUT -i $WAN -p tcp --dport 22 -j ACCEPT
# or only accept from a certain ip
#$IPT -A INPUT -i $WAN -s 125.124.123.122 -p tcp --dport 22 -j ACCEPT

# Accept related and established connections
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Drop netbios from the outside, no log, just drop
$IPT -A INPUT -p udp --sport 137 --dport 137 -j DROP

# Finally, anything which was not allowed yet
# is going to go through our Rejectwall rule
$IPT -A INPUT -j Rejectwall</pre>
</blockquote>
<h3>3.1. Iptables default settings</h3>
<p>First of all, we define where <strong>iptables</strong> binary is located and to make the script easier to attapt to other situation, we define the interface as <em>WAN</em> and <em>LAN</em>.<br />
So, if your machine uses <em>eth1</em> as the interface connected to the Internet and <em>eth0</em> connected to your local network, simply change:</p>
<blockquote>
<p class="dump"> WAN=&#8221;eth0&#8243;<br />
LAN=&#8221;eth1&#8243;</p></blockquote>
<p>to</p>
<blockquote>
<p class="dump"> WAN=&#8221;eth1&#8243;<br />
LAN=&#8221;eth0&#8243;</p></blockquote>
<p>Then we clean up <strong>iptables</strong> by <span class="tech">flushing</span> all the chain and tables:</p>
<blockquote>
<p class="dump">$IPT -F xxx</p>
</blockquote>
<p>and deleting all the <em>optional user-defined chains</em>:</p>
<blockquote>
<p class="dump">$IPT -X</p>
</blockquote>
<p>Then we define the <strong>default policies</strong>:</p>
<blockquote>
<p class="dump">$IPT -P xxx</p>
</blockquote>
<p>Which is to <strong>DROP</strong> any packet which is destinated to the local machine if they were not accepting, <strong>ACCEPT</strong> any packet which is going out of the local machine or going to/coming from our LAN if they were not discarded yet.</p>
<h3>3.2. To and From Local Network</h3>
<p>Because we want to be able to forward traffic, we need to say so to the kernel. This is what is done by setting <span class="tech">/proc/sys/net/ipv4/ip_forward</span> to 1.</p>
<p>Then, we need to tell the kernel to <em>masquerade</em> all <em>outgoing</em> traffic. This is what is achieved by triggering:</p>
<blockquote>
<p class="dump">$IPT -t nat -A POSTROUTING -o $WAN -j MASQUERADE</p>
</blockquote>
<p>Masquerading has the effect of allowing all computer from your internal network to access the internet. These machines will be seen as if there were the router itself.</p>
<p>Now, suppose you want your apache server on machine 192.168.0.2 to be visible from the outside. You need to tell the firewall to send those packets to machine 192.168.0.2 on port 80, this is what is achieved with:</p>
<blockquote>
<p class="dump">$IPT -t nat -A PREROUTING -i $WAN -p tcp &#8211;dport 80 -j DNAT &#8211;to 192.168.0.2:80</p>
</blockquote>
<p>But then, you also need to accept new connection on that specific port because, as you will see later on, we by default forbid <em>NEW</em> and <em>INVALID</em> connections coming from the outside to be forwarded.<br />
So, for that specific service, we will allow <em>NEW</em> connections (<em>RELATED</em> and <em>ESTABLISHED</em> being allowed by default) to be forwarded:</p>
<blockquote>
<p class="dump">$IPT -A FORWARD -i $WAN -p tcp  &#8211;dport 80 -m state &#8211;state NEW -j ACCEPT</p>
</blockquote>
<p>And now, let discard any <em>NEW</em> and <em>INVALID</em> connections:</p>
<blockquote>
<p class="dump">$IPT -A FORWARD -i $WAN -m state &#8211;state NEW,INVALID -j DROP</p>
</blockquote>
<p>To be able to have your local connection to work properly, you need to accept everything on localhost. This is done with:</p>
<blockquote>
<p class="dump"> # Accept any connections from the local machine<br />
$IPT -A INPUT -i lo -j ACCEPT</p></blockquote>
<p class="warning"> We do not need to use the statement <span class="tech">$IPT -A OUTPUT -i lo -j ACCEPT</span> because the default <strong>OUTPUT policy</strong> is set to <strong>ACCEPT</strong><br />
If your default policy is different, you might have to add this statement</p>
<p>Then, because in our example we trust our local network (not a wise thing to do though), we need to allow any incoming connections from our LAN:</p>
<blockquote>
<p class="dump"># plus from your local network<br />
$IPT -A INPUT -i $LAN -j ACCEPT</p></blockquote>
<h3>3.3. Defining custom chains</h3>
<p>In order to get a easier to maintain <strong>iptables</strong> script, it is handy to define some custom chains, also called <em>user-defined chains</em>. This way, you can gather common actions into 1 chain, then, using our target switch (<em>-j</em>) we will be able to send packets that match specific rules to that target.<br />
In order to create a <em>user-defined chain</em>, we need to use:</p>
<blockquote>
<p class="shell">iptables -N chain_name</p>
</blockquote>
<p>and then simply add rules to that chain using the usual:</p>
<blockquote>
<p class="shell">iptables -A chain_name [rules ...] -j target</p>
</blockquote>
<p>Okie, now that this is explained, we are going to create 3 <em>user-defined chains</em> which are going to <span class="system">log</span> packet matching rules to be sent to this specific chain:</p>
<ul>
<li>Firewall: is going to log packets by prepending &#8220;Firewall: &#8221; and DROP them, as you will see, this will only deal with ICMP</li>
<li>Rejectwall: is going to log packets (prepending &#8220;Rejectwall: &#8220;) that were not accepted my any previous rules</li>
<li>Badflags: is going to log packets which TCP flags are not properly set. Some kind of packets are usually used during attack. (prepending &#8220;Badflags: &#8220;)</li>
</ul>
<p>The bit of code that deals with the chain creation and which append rules to it is:</p>
<blockquote>
<p class="dump"> # Here we define a new chain which is going to handle<br />
# packets we don&#8217;t want to respond to<br />
# limit the amount of logs to 10/min<br />
$IPT -N Firewall<br />
$IPT -A Firewall -m limit &#8211;limit 10/minute -j LOG &#8211;log-prefix &#8220;Firewall: &#8221;<br />
$IPT -A Firewall -j DROP</p>
<p># log those packets and inform the sender that the packet was rejected<br />
$IPT -N Rejectwall<br />
$IPT -A Rejectwall -m limit &#8211;limit 10/minute -j LOG &#8211;log-prefix &#8220;Rejectwall: &#8221;<br />
$IPT -A Rejectwall -j REJECT<br />
# use the following instead if you want to simulate that the host is not reachable<br />
# for fun though<br />
#$IPT -A Rejectwall -j REJECT  &#8211;reject-with icmp-host-unreachable</p>
<p># here we create a chain to deal with unlegitimate packets<br />
# and limit the number of alerts to 10/min<br />
# packets will be drop without informing the sender<br />
$IPT -N Badflags<br />
$IPT -A Badflags -m limit &#8211;limit 10/minute -j LOG &#8211;log-prefix &#8220;Badflags: &#8221;<br />
$IPT -A Badflags -j DROP</p></blockquote>
<p>As you can see, there is a new <strong>target</strong> (<em>action</em>), namely <strong>LOG</strong>. <strong>LOG</strong> is a specific target that logs the packet to /var/log/messages usually. <strong>LOG</strong> is a <em>non-terminating target</em>, this means that the packet is going to continue to the next rule after being logged.<br />
by using the <em>&#8211;log-prefix</em> you can specify what is going to be prepended to your log.</p>
<p>So let&#8217;s take the example of chain &#8220;Firewall&#8221;.<br />
First we create the chain: <em>$IPT -N Firewall</em><br />
Then, we ask the kernel to log the packet and to prepend &#8220;Firewall: &#8221; to the log string. But because we don&#8217;t want our logs to be flooded by such logs, we cap the number of logs related to the Firewall chain to 10/minute: <em>$IPT -A Firewall -m limit &#8211;limit 10/minute -j LOG &#8211;log-prefix &#8220;Firewall: &#8220;</em><br />
Finally, after we logged the packet, we are simply going to DROP it: <em>$IPT -A Firewall -j DROP</em></p>
<h3>3.4. Using those rules</h3>
<p>Creating <em>user-defined chain</em> will now make it easier and faster for us to operate specific actions on packets.<br />
Let&#8217;s go through the block of statements related to bad TCP flags:</p>
<blockquote>
<p class="dump"> # A list of well known combination of Bad TCP flags<br />
# we redirect those to the Badflags chain<br />
# which is going to handle them (log and drop)<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ACK,FIN FIN -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ACK,PSH PSH -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ACK,URG URG -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags FIN,RST FIN,RST -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags SYN,FIN SYN,FIN -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags SYN,RST SYN,RST -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ALL ALL -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ALL NONE -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ALL FIN,PSH,URG -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ALL SYN,FIN,PSH,URG -j Badflags<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ALL SYN,RST,ACK,FIN,URG -j Badflags</p></blockquote>
<p>As you can see, for any of the packet matching a rule, we simply have to send the packet to the &#8220;<em>Badflags</em>&#8221; chain. If we were not using <em>user-defined chains</em>, the first statement would look like:</p>
<blockquote>
<p class="dump"> $IPT -A INPUT -p tcp &#8211;tcp-flags ACK,FIN FIN -m limit &#8211;limit 10/minute -j LOG &#8211;log-prefix &#8220;Badflags: &#8221;<br />
$IPT -A INPUT -p tcp &#8211;tcp-flags ACK,FIN FIN -j DROP</p></blockquote>
<p>So this would be twice as much work :s. Now, imagine you want to change the target from DROP to REJECT, you simply have to edit 1 line instead of 11 <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p class="tip">Those badflags rules are well known combinations of illegitimated TCP flags settings. Normal application should not use those, this is why we can DROP those packets safely.</p>
<p>Now, we are going to allow only a small set of <span class="tech">ICMP</span> packets. In our example, we want our firewall to be able to receive information such as <em>Timeout</em> (type 11), <em>Host unreachable</em> (type 3) and we want it to reply to pings (type 8 ) and get replies to ping initiated from our firewall (type 0).<br />
In order to do this, we ACCEPT any <em>ICMP</em> packets which contains one of the following code type and then pass all other <em>ICMP</em> packets code to our <strong>Firewall</strong> chain.</p>
<blockquote>
<p class="dump"> # Accept certain icmp message, drop the others<br />
# and log them through the Firewall chain<br />
# 0 =&gt; echo reply<br />
$IPT -A INPUT -p icmp &#8211;icmp-type 0 -j ACCEPT<br />
# 3 =&gt; Destination Unreachable<br />
$IPT -A INPUT -p icmp &#8211;icmp-type 3 -j ACCEPT<br />
# 11 =&gt; Time Exceeded<br />
$IPT -A INPUT -p icmp &#8211;icmp-type 11 -j ACCEPT<br />
# 8 =&gt; Echo<br />
# avoid ping flood<br />
$IPT -A INPUT -p icmp &#8211;icmp-type 8 -m limit &#8211;limit 1/second -j ACCEPT<br />
$IPT -A INPUT -p icmp -j Firewall</p></blockquote>
<p class="tip">Note the <span class="tech">-m limit &#8211;limit 1/second</span>, by doing such, our firewall is going to reply to only 1 ping per second, any other ping will be logged (up to 10/min and then DROPped) through the <em>Firewall</em> chain</p>
<h3>3.5. Traffic from the Internet</h3>
<p>After we have dealt with not well formed packets and icmp packets, we should apply some global rules to streams coming from the outside (remember that our default policy for OUTPUT packets is ACCEPT, so we don&#8217;t have to allow those).</p>
<p>The basic idea here is to only allow streams that are related to a previous connection (useful for FTP for instance) or already established.<br />
But, we are going to make one exception for <span class="tech">SSH</span> because we want to be able to connect to our box from the outside.</p>
<p>We achieve this by accepting any ssh packets from the outside and then only connections in state RELATED or ESTABLISHED</p>
<blockquote>
<p class="dump"> # Accept ssh connections from the Internet<br />
$IPT -A INPUT -i $WAN -p tcp &#8211;dport 22 -j ACCEPT<br />
# or only accept from a certain ip<br />
#$IPT -A INPUT -i $WAN -s 125.124.123.122 -p tcp &#8211;dport 22 -j ACCEPT</p>
<p># Accept related and established connections<br />
$IPT -A INPUT -m state &#8211;state RELATED,ESTABLISHED -j ACCEPT</p></blockquote>
<p>Then we are going to DROP silently netbios scan from the outside:</p>
<blockquote>
<p class="dump"> # Drop netbios from the outside, no log, just drop<br />
$IPT -A INPUT -p udp &#8211;sport 137 &#8211;dport 137 -j DROP</p></blockquote>
<p>And finally, REJECT any other packet through our user-defined chain <em>Rejectwall</em>:</p>
<blockquote>
<p class="dump"> $IPT -A INPUT -j Rejectwall</p>
</blockquote>
<h2>4. Using iptables&#8217;script</h2>
<h3>4.1. From the command line</h3>
<p>One way to apply the rules we define, is simply to run the script from the command line like:</p>
<p class="shell">sudo sh /path/to/firewall-script.sh</p>
<p>but this has the bad effect of not being restore on reboot :s, but still, this will be of great help while tweaking up your firewall.</p>
<h3>4.2. Using /etc/rc.local</h3>
<p><strong>/etc/rc.local</strong> is a custom file where you can add scripts to be executed at the end of each multiuser runlevel.</p>
<p>By default, this file only contain <em>exit 0</em>.<br />
In order to have your iptables firewall script executed on reboot, simply add the path to your firewall script before <em>exit 0</em>.</p>
<p>Copy your firewall script file to /etc/firewall-script.sh for instance. Then make it executable:</p>
<blockquote>
<p class="shell">sudo chmod 700 /etc/firewall-script.sh</p>
</blockquote>
<p>Then edit /etc/rc.local and add <em>/etc/firewall-script.sh</em> before exit 0</p>
<p>Next time you are going to reboot, this script is going to be executed and therefore, your firewall set up restored.</p>
<h3>4.3. Using /etc/network/if-up.d/ directory</h3>
<p>This one is a bit more tricky.<br />
Once you are done with setting up your firewall script, you will save it to the <em>iptables format</em> by trigerring:</p>
<p class="shell"> $sudo sh /path/to/firewall/script.sh<br />
$sudo iptables-save &gt; /etc/firewall-iptables.conf</p>
<p>Now, open and edit <em>/etc/network/if-up.d/iptables</em> and make it look like:</p>
<blockquote>
<pre class="file">#!/bin/sh
iptables-restore &lt; /etc/firewall-iptables.conf</pre>
</blockquote>
<p>Then make it executable:</p>
<blockquote>
<p class="shell">sudo chmod +x /etc/network/if-up.d/iptables</p>
</blockquote>
<p>Finally, we need a way to set up <em>/proc/sys/net/ipv4/ip_forward</em> to 1. This can be achieved through <span class="tech">/etc/sysctl.conf</span>.<br />
Simply add the following entry if not already there:</p>
<blockquote>
<p class="dump">net.ipv4.ip_forward=1</p>
</blockquote>
<p>which will set /proc/sys/net/ipv4/ip_forward to 1 next time you reboot.</p>
<p class="tip">We could have also used /etc/firewall-script.sh instead of the <em>iptables-restore</em> trick, but this way, you can see another way to do it</p>
<p>Reboot, your firewall should be up again <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>4.4. Once upon a time</h3>
<p>Debian used to have this great <span class="tech">/etc/init.d/iptables</span> init script which allowed you to restore iptables settings on boot up, stop your firewall &#8230;<br />
This script is now gone&#8230; so we have got to do it by ourself now <img src='http://www.hlouis.com/hlouis_com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h3>4.5. Rescue script</h3>
<p>A handy script to have around is a script that can erase all chains and rules in case you are getting lost with your firewall breakages. The following script will clear up all rules and reset all chain so your firewall will be inactive. I suggest you copy it and keep it somewhere close to you in case of emergency.</p>
<blockquote><p>#!/bin/bash<br />
IPT=&#8217;/sbin/iptables&#8217;</p>
<p>for a in `cat /proc/net/ip_tables_names`; do<br />
${IPT} -F -t $a<br />
${IPT} -X -t $a</p>
<p>if [ $a = nat ]; then<br />
${IPT} -t nat -P PREROUTING ACCEPT<br />
${IPT} -t nat -P POSTROUTING ACCEPT<br />
${IPT} -t nat -P OUTPUT ACCEPT<br />
elif [ $a = mangle ]; then<br />
${IPT} -t mangle -P PREROUTING ACCEPT<br />
${IPT} -t mangle -P INPUT ACCEPT<br />
${IPT} -t mangle -P FORWARD ACCEPT<br />
${IPT} -t mangle -P OUTPUT ACCEPT<br />
${IPT} -t mangle -P POSTROUTING ACCEPT<br />
elif [ $a = filter ]; then<br />
${IPT} -t filter -P INPUT ACCEPT<br />
${IPT} -t filter -P FORWARD ACCEPT<br />
${IPT} -t filter -P OUTPUT ACCEPT<br />
fi</p></blockquote>
<pre class="file">done</pre>
<h2>5. Conclusion</h2>
<p>This tutorial covered <strong>iptables</strong> in order to set up a linux firewall which will share your internet connection amongst computer from your local network.<br />
By explaining <strong>iptables</strong> basis, you should now be able to improve your script so you can allow or disallow specific types of traffic.</p>
<p>This is not the most secure set up though. Best practice would be to set up a policy which disallow all traffic by default and then only allow the traffic you believe that should be permitted.</p>
<p>Finally we went through different ways of recovering iptables setting on reboot.</p>
<p>Hope this helps and will give you enough basis to customize your firewall.</p>
<p class="dump">&nbsp;</p>
<blockquote>
<p class="dump"><a href="http://www.hlouis.com/hlouis_com/wp-content/uploads/2007/11/firewall-simple.txt" title="firewall-simple.txt">firewall-simple.txt<br />
</a><a href="http://www.hlouis.com/hlouis_com/wp-content/uploads/2007/11/firewall-stop.txt" title="firewall-stop.txt">firewall-stop.txt</a><a href="http://www.hlouis.com/hlouis_com/wp-content/uploads/2007/11/firewall-simple.txt" title="firewall-simple.txt"><br />
</a></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.hlouis.com/develop/linux/iptables-how-to-share-your-internet-connection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
