<?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/" >
<channel>
	<title>星空博客</title>
	<link>http://www.xklog.org</link>
	<description>XKLog! 开源个人博客系统！值得选择的个人网志平台！</description>
	<language>zh-cn</language>
	<copyright>Powered By XKLog V0.7.244.Copyright 2010 星空博客 All Rights Reserved.</copyright>
	<pubDate>Mon, 06 Sep 2010 01:57:25 +0000</pubDate>
	<generator>XKLog V0.7.244</generator>
	
	<item>
		<title><![CDATA[高数也可以这么诗意]]></title>
		<link>http://www.xklog.org/article/internet/math-can-be-so-poetic.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>拉格朗日，<br />
傅立叶旁，<br />
我凝视你凹函数般的脸庞。<br />
微分了忧伤，<br />
积分了希望，<br />
我要和你追逐黎曼最初的梦想。<br />
感情已发散，<br />
收敛难挡，<br />
没有你的极限，<br />
柯西抓狂，<br />
我的心已成自变量，<br />
函数因你波起波荡。<br />
低阶的有限阶的，<br />
一致的不一致的，<br />
是我想你的皮亚诺余项。<br />
<br />
狄利克雷，<br />
勒贝格杨<br />
一同仰望莱布尼茨的肖像，<br />
拉贝、泰勒，无穷小量，<br />
是长廊里麦克劳林的吟唱。<br />
打破了确界，<br />
你来我身旁，<br />
温柔抹去我，<br />
阿贝尔的伤，<br />
我的心已成自变量，<br />
函数因你波起波荡。<br />
低阶的有限阶的，<br />
一致的不一致的，<br />
是我想你的皮亚诺余项。<br />
<br />
<font color="#ff0000"><strong>青花瓷 之 高数版</strong></font><br />
<br />
信笔勾勒出坐标<br />
思路明转暗<br />
空间描绘的曲线<br />
一如你出场<br />
逐项积分求过导<br />
后事我茫然<br />
稿纸上走笔至此搁一半<br />
<br />
函数展成傅立叶<br />
系数被私藏<br />
而你收敛的一笑<br />
如二次曲面<br />
你的美一缕发散<br />
去到我去不了的地方<br />
<br />
右手规则解叉积<br />
而我在解你<br />
泰勒悄悄用起<br />
式子千万里<br />
在课本书积分仿牛顿的飘逸<br />
就当我为读懂你伏笔<br />
<br />
变量代换算周期<br />
而我在算你<br />
高斯被打捞起<br />
明白了结局<br />
如传世的洛必达自顾自美丽<br />
你眼带笑意<br />
<br />
逐渐逼近的级数跃然于眼里<br />
临摹柯西落笔却惦记着你<br />
你隐藏在方程里百年的秘密<br />
极细腻犹如绣花针落地<br />
收敛半径惹连续<br />
区间惹值域<br />
<br />
而我使用那三重积分惹了你<br />
在旋转抛物面里<br />
你从截痕深处被隐去<br />
<br />
<font color="#ff0000"><strong>兰亭序 之 高数版</strong></font><br />
<br />
数分难学 高数如高山流水<br />
函数数列 何时也为我收敛<br />
开和闭 区间易理解 却难求你极限<br />
映射也 映不进心间<br />
<br />
函数连续 却也不一定可导<br />
然而可导 竟又一定会可微<br />
导数高阶 问莱布尼茨 他到底是个谁<br />
有间断点 而我不曾觉<br />
<br />
费马初现 我渐渐入深渊<br />
罗尔浅笑 顿觉头晕目眩<br />
拉格朗日 落井下石最会<br />
而我独缺 对柯西的了解<br />
<br />
费马初现 我渐渐入深渊<br />
罗尔浅笑 顿觉头晕目眩<br />
拉格朗日 落井下石最会<br />
而我独缺 对柯西的了解<br />
<br />
费马初现 我渐渐入深渊<br />
罗尔浅笑 顿觉头晕目眩<br />
拉格朗日 落井下石最会<br />
而我独缺 对柯西的了解<br />
<br />
水笔疾飞 草稿顷刻间湮灭<br />
铃声响却 佩亚诺才刚出现<br />
展开没 泰勒很复杂 麦克劳林简约<br />
求极限 洛必达无愧<br />
<br />
人事纷飞 单调改用求导解<br />
凸还是凹 目测早已不精确<br />
试卷最黑 题设常千山万水 总被蒙骗<br />
驻点拐点 到底谁是谁<br />
<br />
费马初现 我渐渐入深渊<br />
罗尔浅笑 顿觉头晕目眩<br />
拉格朗日 落井下石最会<br />
而我独缺 对柯西的了解<br />
<br />
费马初现 我渐渐入深渊<br />
到底等谁 伯努利傅里叶<br />
几人痴醉 却恨透了数学<br />
我最可悲 只爱上你的美<br />
<font color="#ff0000"><strong><br />
爱在西元前 之 高数版</strong></font><br />
<br />
多元函数突破了横纵坐标的局限<br />
穿过了垂直的Z轴<br />
扩展到三维立体空间里面<br />
你在曲线前<br />
凝视方程的字眼<br />
我却在旁焦头烂额忙着初等函数的换元<br />
<br />
单调 间断 凹凸 拐点<br />
是谁的判断<br />
喜欢在夹逼定理后你只属于我的那极限<br />
经过无穷级数的计算<br />
我以欧拉之名许愿<br />
思念想正余弦函数般蔓延<br />
<br />
当微分方程只剩下未知的概念<br />
通解就成了永恒不变的诗篇<br />
<br />
我给你的爱写在求导前<br />
深埋在极限定义连续里面<br />
洛必达法则后发现<br />
所求的结果依然清晰可见<br />
<br />
我给你的爱写在积分前<br />
深埋在几何区域面积里面<br />
用二次曲面写下了永远<br />
那些极坐标代换的经典<br />
一切又重演<br />
<br />
我感到很疲倦<br />
思路少的好可怜<br />
害怕再也不能无限接近到你身边</p>]]></description>
		<category>网海拾贝</category>
		<guid>http://www.xklog.org/article/internet/math-can-be-so-poetic.html</guid>
		<pubDate>Sat, 24 Jul 2010 07:34:59 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[iptables 真害人 = =]]></title>
		<link>http://www.xklog.org/article/study/iptables-F-INPUT.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>&hellip;&hellip;还有一种情况，就是要清空整个链，这就要使用选项<strong class="COMMAND">-F</strong>。比如，我们要清空整个 INPUT链，使用的命令就是<strong class="COMMAND">iptables -F INPUT</strong>。<font color="#ff0000">但是要注意，选项<strong class="COMMAND">-F</strong>并不改变链的缺省策 略。所以，如果被我们清空的那条INPUT链的策略是DROP，它还是会阻塞所有的包</font>。那怎么才能重置策略呢？ 还记得策略DROP是如何设置的吧，还是用那个方法啊。比如，我们把INPUT链的策略改为ACCEPT，就用<strong class="COMMAND">iptables -P INPUT ACCEPT</strong>。<br />
<br />
我傻乎乎地执行了一下 <strong class="COMMAND">iptables -F INPUT</strong><span class="COMMAND">，于是不得不请机房帮我重启服务器了。</span></p>]]></description>
		<category>学习笔记</category>
		<guid>http://www.xklog.org/article/study/iptables-F-INPUT.html</guid>
		<pubDate>Fri, 23 Jul 2010 16:53:25 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[LINUX下的SYN攻击防御]]></title>
		<link>http://www.xklog.org/article/internet/Linux-SYN-attack.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>在怀疑有Dos攻击的时候，可以输入<br />
netstat -an | grep -i &ldquo;服务器ip地址:80&Prime; | awk &lsquo;&rsquo;{print }'&rsquo; | sort | uniq -c | sort -n</p>
<p>这个命令会自动统计Tcp连接各个状态的数量，如果SYN_RECV很高的话，就不能排除有基于tcp协议的ddos攻击的可能，这个时候可以打开tcp_syncookies，输入如下命令</p>
<p>echo 1 &gt; /proc/sys/net/ipv4/tcp_syncookies</p>
<p>如果没有 /proc/sys/net/ipv4/tcp_syncookies说明你的内核不支持，需要重新编译内核<br />
同时 降低syn重试次数<br />
echo 1 &gt; /proc/sys/net/ipv4/tcp_syn_retries<br />
echo 1 &gt; /proc/sys/net/ipv4/tcp_synack_retries</p>
<p>加大syn_backlog，以保证用户的访问（消耗内存为代价，设的太高。。）</p>
<p>echo &ldquo;2048&Prime; &gt; /proc/sys/net/ipv4/tcp_max_syn_backlog</p>
<p>如果还是不行，那么只能交给相应的硬件防火墙了。</p>
<p><span class="tpc_content"><font color="indigo">#防止SYN攻击 轻量<br />
/sbin/iptables -N syn-flood<br />
/sbin/iptables -A INPUT -p tcp --syn -j syn-flood<br />
/sbin/iptables -I syn-flood -p tcp -m limit --limit 3/s --limit-burst 6 -j RETURN<br />
/sbin/iptables -A syn-flood -j REJECT<br />
#为了防止DOS太多连接进来,那么可以允许最多15个初始连接,超过的丢弃<br />
<br />
/sbin/iptables -A INPUT -s $INNET -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT<br />
/sbin/iptables -A INPUT -i $EXTIF -p tcp --syn -m connlimit --connlimit-above 15 -j DROP<br />
/sbin/iptables -A INPUT -s $INNET -p tcp --syn -m connlimit --connlimit-above 15 -j DROP<br />
<br />
#设置icmp阔值 ,并对攻击者记录在案<br />
/sbin/iptables -A INPUT -p icmp -m limit --limit 3/s -j LOG --log-level INFO --log-prefix &quot;ICMP packet IN: &quot;<br />
/sbin/iptables -A INPUT -p icmp -m limit --limit 6/m -j ACCEPT<br />
/sbin/iptables -A INPUT -p icmp -j DROP</font></span></p>
<p># 防止端口扫描</p>
<p>iptables -I INPUT -p icmp --icmp-type echo-request -m state --state NEW -j DROP #禁止PING</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP #标志为FIN，URG，PSH拒绝</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags SYN,RST SYN,RST -j DROP</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL ALL -j DROP</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP</p>
<p>iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL NONE -j DROP</p>
<p>（附：218。94。6。179/188两台服务器安装的WEBMIN限定*。181网关连接，密码为：fangzhi790529）</p>
<p># 防止SYN FLOOD攻几！</p>
<p>iptables -N synfoold<br />
iptables -A synfoold -p tcp --syn -m limit --limit 1/s -j RETURN<br />
iptables -A synfoold -p tcp -j REJECT --reject-with tcp-reset<br />
iptables -A INPUT -p tcp -m state --state NEW -j synfoold</p>
<p># 禁止PING</p>
<p>iptables -N ping<br />
iptables -A ping -p icmp --icmp-type echo-request -m limit --limit 1/second -j RETURN<br />
iptables -A ping -p icmp -j REJECT<br />
iptables -I INPUT -p icmp --icmp-type echo-request -m state --state NEW -j ping</p>
<p># 端口过滤</p>
<p>#這個 script 內容，很適用只允許外面連結特定的 port 服務，剩下的其餘<br />
&nbsp;&nbsp;port 就拒絕外面主動建立的連線。</p>
<p>&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 21 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 389 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 1002 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 1720 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p udp --dport 2121 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 3306 -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 8009 -j ACCEPT</p>
<p>&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 8080 -j ACCEPT</p>
<p>&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 8081 -j ACCEPT</p>
<p>&nbsp;&nbsp;iptables -A INPUT -i eth0 -p tcp --dport 10000 -j ACCEPT</p>
<p mso-char-indent-count:="" text-indent:=""><br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT<br />
&nbsp;&nbsp;iptables -A INPUT -i eth0 -m state --state NEW,INVALID -j DROP</p>
<p mso-char-indent-count:="" text-indent:="">&nbsp;</p>
<p mso-char-indent-count:="" text-indent:="">ipdrop <br />
如果能创建一个特殊的&quot;ipdrop&quot;脚本，其被设计为能方便地插入一个规则来阻塞指定的IP，那么将上面的工作将非常容易。通过该脚本阻塞某个IP将 是非常容易的工作，只需要几秒钟就可以实现。而且通过该脚本还可以防止手工加入规则时容易出现的错误。因此阻塞黑客的攻击将变为确定其攻击源地址。然后通 过如下命令： <br />
<br />
# ipdrop 129.24.8.1 on <br />
IP 129.24.8.1 drop on. <br />
ipdrop脚本将立即阻塞129.24.8.1。通过使用该脚本能显著地提高你的防卫能力。下面就是ipdrop脚本的实现： <br />
The ipdrop bash script <br />
<br />
#!/bin/bash <br />
source /usr/local/share/dynfw.sh <br />
args 2 $# &quot;${0} IPADDR {on/off}&quot; &quot;Drops packets to/from IPADDR. Good for obnoxious networks/hosts/DoS&quot; <br />
if [ &quot;$2&quot; == &quot;on&quot; ] <br />
then <br />
#rules will be appended or inserted as normal <br />
APPEND=&quot;-A&quot; <br />
INSERT=&quot;-I&quot; <br />
rec_check ipdrop $1 &quot;$1 already blocked&quot; on <br />
record ipdrop $1 <br />
elif [ &quot;$2&quot; == &quot;off&quot; ] <br />
then <br />
#rules will be deleted instead <br />
APPEND=&quot;-D&quot; <br />
INSERT=&quot;-D&quot; <br />
rec_check ipdrop $1 &quot;$1 not currently blocked&quot; off <br />
unrecord ipdrop $1 <br />
else <br />
echo &quot;Error: &quot;off&quot; or &quot;on&quot; expected as second argument&quot; <br />
exit 1 <br />
fi <br />
#block outside IP address thats causing problems <br />
#attackers incoming TCP connections will take a minute or so to time out, <br />
#reducing DoS effectiveness. <br />
iptables $INSERT INPUT -s $1 -j DROP <br />
iptables $INSERT OUTPUT -d $1 -j DROP <br />
iptables $INSERT FORWARD -d $1 -j DROP <br />
iptables $INSERT FORWARD -s $1 -j DROP <br />
echo &quot;IP ${1} drop ${2}.&quot; <br />
<br />
ipdrop:解释 <br />
从上面的脚本源代码中最后四行内容可以看到实际的命令是在防火墙表中插入适当的规则。可以看到$INSERT变量的值取决于在命令行参数中是使用&quot;on&quot;还是&quot;off&quot;模式。当iptables行被执行时特定的规则将被适当的插入或删除。 <br />
现在我们看看这些规则本身的功能，它们能和任何类型的防火墙一起发挥作用，甚至在没有部署防火墙的系统上。需要的条件仅仅是支持iptables的 Linux2.4版本的内核。我们阻塞来自恶意IP的攻击数据报(第一条iptables语句)，阻塞发向恶意攻击IP的数据报(第二条iptables 语句)，并且对该IP关闭任意方向的数据转发(最后两条iptables工具)。一旦这些规则发挥作用系统将丢弃满足这些条件的任何数据报。 <br />
另外一个需要注意的是：脚本中调用了&quot;rec_check&quot;, &quot;unrecord&quot;,  &quot;record&quot;,和&quot;args&quot;。这些都是定义在&quot;dynfw.sh&quot;中的特殊的bash函数。&quot;record&quot;函数实现将被阻塞的IP记录在文件 /root/.dynfw-ipdrop文件中，而&quot;unrecord&quot;则是将其从文件/root/.dynfw-ipdrop中去 除。&quot;rec_check&quot;函数是在发现试图重新阻塞某个已经阻塞的IP地址或取消某个没有被阻塞的IP地址时输出错误信息并停止脚本执行。&quot;args&quot; 函数实现确保命令行参数的正确性，并实现打印脚本帮助命令。文件dynfw-1.0.tar.gz包含所有的这些工具。 <br />
<br />
tcplimit <br />
<br />
如果你需要对某个特殊的基于TCP的网络服务的使用进行限制(例如在端系统上产生严重负载时)，则tcplimit脚本则可以帮助你达到这个目的，该脚本使用TCP端口、一个率值和&quot;on&quot;或&quot;off&quot;作为参数： <br />
<br />
# tcplimit 873 5 minute on <br />
Port 873 new connection limit (5/minute, burst=5) on. <br />
<br />
tcplimit使用iptables的&quot;state&quot;模块(应确保在内核中打开该选项或加载模块)来实现在某段时间内只允许特定数目的连接请求通过。 在本例中防火墙将限制每分钟只允许5个新连接到我的rsync服务器(port 873)。当然你可以根据需要选择时间单位为秒钟/分钟/小时。 <br />
tcplimit提供了一个限制对非关键服务的使用的非常好的方法－这样大量到非关键服务的数据不会破坏服务器。在上面的例子中使用tcplimit来 设置使用rsync的限制，以防止tsync数据占用了Internet连接的所有带宽。其中连接服务限制信息记录在文件/root/.dynfw- tcplimit中。若想关闭该限制只需要键入如下命令： <br />
<br />
# tcplimit 873 5 minute off <br />
Port 873 new connection limit off. <br />
<br />
tcplimit通过在&quot;filter&quot;表中创建一个新的规则链来实现。这个新的规则链将拒绝所有超过指定限制的数据报，同时将一个规则插入到 INPUT规则链中，其将所有的到目标端口(在本例中是873端口)的新连接数据报定向到这个新的规则链。新规则链只会影响新的超过限制的连接而不会影响 已经建立的连接。 <br />
当tcplimit定义的规则被关闭，INPUT规则和新规则链则会被删除。象ipdrop一样其tcplimit可以和任何类型的防火墙一起工作。 <br />
<br />
host-tcplimit <br />
<br />
host-tcplimit和tcplimit非常类似，但是它是限制来自一个特定的IP的到服务器上某个特定端口的TCP连接数量。host- tcplimit在防止某个特定的人滥用你的网络资源时非常有用处。例如你维护有一个CVS服务器，有一天突然发现一个特殊的新开发者出现了，他好像建立 了一个脚本每十分钟更新它的资源。占用了大量的网络资源。 <br />
<br />
对于这种情况，使用host-tcplimit可以非常容易的解决问题： <br />
<br />
# host-tcplimit 1.1.1.1 2401 1 day on <br />
<br />
现在IP地址为1.1.1.1被限制为每天只能进行一次CVS连接从而节省了网络带宽。</p>]]></description>
		<category>网海拾贝</category>
		<guid>http://www.xklog.org/article/internet/Linux-SYN-attack.html</guid>
		<pubDate>Fri, 23 Jul 2010 15:30:24 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[CentOS命令提示符设定]]></title>
		<link>http://www.xklog.org/article/internet/CentOS-bash.html</link>
		<author>星空泪</author>
		<description><![CDATA[<pre>CentOS命令提示符更改设定方法：</pre>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如现在是使用root用户：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;临时性使用直接执 行 <span style="color: rgb(255, 0, 0);"># PS1='[\u@\h \w \t *\#]\$空格' </span>， 执行之后结果为---&gt;&gt; <span style="color: rgb(255, 0, 0);">[root@test2  /var/local 15:59:06 *4]# </span>（这当root用户退出后即将失效）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;若想永久保存 <span style="color: rgb(255, 0, 0);">[root@test2 /var/local 15:59:06 *4]# </span>这 种格式，那么把<span style="color: rgb(255, 0, 0);">PS1=&lsquo;[\u@\h \w \t *\#]\$空格&rsquo; </span>， 加到 vi /root/.bashrc里重启即可。</p>
<p><span style="color: rgb(128, 0, 0);"><span style="font-size: small;"><strong>【所对应参数解析】：&nbsp;</strong></span>&nbsp;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<ul>
    <li>\d ∶代表日期，格式为 Weekday Month Date，例如 &quot;Mon Aug 1&quot;</li>
    <li>\H  ∶完整的主机名称。举例来说，鸟哥的练习机 linux.dmtsai.tw ，那么这个主机名称就是 linux.dmtsai.tw</li>
    <li>\h ∶仅取主机名称的第一个名字。以上述来讲，就是 linux 而已， .dmtsai.tw 被省略。</li>
    <li>\t  ∶显示时间，为 24 小时格式，如∶ HH:MM:SS</li>
    <li>\T ∶显示时间，12 小时的时间格式！</li>
    <li>\A  ∶显示时间，24 小时格式， HH:MM</li>
    <li>\u ∶目前使用者的帐号名称；</li>
    <li>\v ∶BASH  的版本资讯；</li>
    <li>\w ∶完整的工作目录名称。家目录会以 ~ 取代；</li>
    <li>\W ∶利用 basename  取得工作目录名称，所以仅会列出最后一个目录名。</li>
    <li>\# ∶下达的第几个指令。</li>
    <li>\$  ∶提示字元，如果是 root 时，提示字元为 # ，否则就是 $ ～</li>
</ul>]]></description>
		<category>网海拾贝</category>
		<guid>http://www.xklog.org/article/internet/CentOS-bash.html</guid>
		<pubDate>Mon, 19 Jul 2010 19:38:18 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[利用AJAX模拟HTTP长连接(LongPoll)来实现”服务器推”技术]]></title>
		<link>http://www.xklog.org/article/internet/comet-ajax-longpoll-push.html</link>
		<author>星空泪</author>
		<description><![CDATA[<blockquote>
<p>Comet（彗星：某人给服务器推送技术起的名字）</p>
</blockquote>
<p><strong>核心图解：</strong><br />
<img src="/upload/201007/2010071203453956.jpg" alt="" /></p>
<blockquote>
<p>最近在看&ldquo;服务器推送技术&rdquo;，在B/S结构中，通过某种magic使得客户端不需要通过轮询即可以得到服务端的最新信息 （比如股票价格，聊天室，webQQ、开心网、白社会），这样可以节省大量的带宽。</p>
<p>传统的轮询技术对服务器的压力很大，并且造成带宽的极大浪费。如果改用ajax轮询，可以降低带宽的负荷（因为服务器返回的不是完整页面），但是对 服务器的压力并不会有明显的减少。</p>
<p>而推技术（push）可以改善这种情况。但因为HTTP连接的特性（短暂，必须由客户端发起），使得推技术的实现比较困难，常见的做法是通过延长 http连接的寿命，来实现push。</p>
</blockquote>
<p><strong>基本实现原理：</strong></p>
<blockquote>
<p>接下来自然该讨论如何延长http连接的寿命，最简单的自然是死循环法，如果使用观察者模式则可以进一步提高性能。</p>
<p>但是这种做法的缺点在于客户端请求了这个servlet后，web服务器会开启一个线程执行servlet的代码，而servlet由迟迟不肯结 束，造成该线程也无法被释放。于是乎，一个客户端一个线程，当客户端数量增加时，服务器依然会承受很大的负担。</p>
<p>要从根本上改变这个现象比较复杂，目前的趋势是从web服务器内部入手，用nio（JDK  1.4提出的java.nio包）改写request/response的实现，再利用线程池增强服务器的资源利用率，从而解决这个问题，目前支持这一非 J2EE官方技术的服务器有Glassfish和Jetty。目前也有一些框架/工具可以帮助你实现推功能，比如pushlets。不过没有深入研究。还 有就是通过设置超时来解决。</p>
</blockquote>
<p><strong>在客户和服务器之间保持&ldquo;心跳&rdquo;信息 &mdash;&ndash;无事件导致超时处理：</strong></p>
<blockquote>
<p>因为服务器为了保持请求（阻塞请求），必须有一个无限循环，循环的结束条件就是获取到了返回结果，如果客户端关闭了（客户 端浏览器的关闭不会发消息给服务器），服务器无法知道客户端已经关了，这个请求没必要处理下去了，最终会造成资源过度浪费。还有服务器中间可能存在各式各 样配置怪异的网关和代理，它们上面可能有各式各样的超时规则，因此Comet最好设计为定期重连。只要用一个折中的办法，限制超时时间。一般情况下，如果 30秒没有任何事件发生，服务器端就应该通知客户端确实没有事件发生，结束掉本次请求，然后重新开始一次新的请求以便继续等待。这里可以不必设置客户端 ajax的超时时间，但进行请求的时候传递一个超时值给服务器，服务器在处理的时候，如果超时时间到了的话，还没有客户端需要的结果，这时传递一个超时信 息给客户端，客户端接收到了此信息，根据情况重新进行ajax请求，也就是进入下一个轮询&hellip;&hellip;&hellip;.当服务器处理信息出现异常情况，需要发送错误信息通知客 户端，同时释放资源、关闭连接。</p>
</blockquote>
<p><strong>服务器端事件队列管理以及如何保持可靠的消息队列:</strong></p>
<blockquote>
<p>由于ajax的LongPoll是拉的方式(不同的客户端拉取的参数可以根据客户端不同而不同)，服务器端根据客户选择的 方式在读取事件队列（fetchEvents）时进行不同的处理，会把&ldquo;heartbeat&rdquo;与&ldquo;refresh&rdquo;事件一起传给客户端，通知客户端重新发 出请求、建立连接。拉的同时也解决了发送目标的返回值。</p>
<p>在这里我们可以想象一个可能发生的情况，服务器端向你发送一个消息，你没有成功接收，但是服务器端认为发送了就成功了，消息从队列删除了，然后这个 消息就永久丢失掉了。可能有人会强调TCP多么可靠，服务器端发送的消息如果在TCP的层面发生问题了，肯定会引发Socket级别的 Exception，这个Exception冒泡上来，服务器端就能截获，从而得知发送失败，然后先不删除队首消息。可是别忘了，中间是可能存在代理的， 如果代理成功把消息收回去了，可是代理发送到客户端这一步失败了，服务器端就不一定会发生异常了。</p>
<p>因此，我们需要制定一种策略，来确保下行消息总能发送到客户端。在这里，我们选择了引入逐个ACK的机制，来确认消息的接收。也就是说，服务器端发 送给客户端的消息带有一个序号，在客户端收到消息后就将该序号发回给服务器端，已确认它受到了该消息。在下次请求时就将该序号加1的值通过 sequence参数传递回去，让服务器知道我们期望下一条消息的编号是这个。例如我们收到Message，其Sequence属性为836，那么下一次 调用的时候就传给服务器837。服务器端此时应该保留了编号为836的Message在对首，如果客户端继续请求836号消息，证明它上次没收到，这次仍 然发送836号消息给它；如果客户端请求837号消息，证明它成功收到836号消息的，这次就发送837号消息给它。看到这里是不是感觉有点熟悉了，不 错，这有点类似经典的TCP三握手原理。如果都不是，那该怎么办？那意味着，这是一个错误的请求，甚至可能是攻击请求，因为正常情况下不应该出现这样的请 求的，服务器端可以考虑抛个无关紧要的Exception（不要告诉攻击者你知道他在攻击了），甚至直接给个400 （bad  request）的响应代号。</p>
</blockquote>
<p><strong>国外一个简单的聊天室例子：</strong><br />
我们需要4个文件:<br />
A file to exchange data (data.txt)<br />
A PHP script that will handle the persistent http request (backend.php)<br />
A HTML file that will load Javascript code and that will show the data  coming from the server (index.html)<br />
The prototype library that will help us to write simple JS code</p>
<p><strong>服务端backend.php：</strong><br />
做2件事：<br />
Write into &ldquo;data.txt&rdquo; when new messages are sent<br />
Do an infinite loop as long as &ldquo;data.txt&rdquo; file is unchanged</p>
<div class="hl-surround">
<div class="hl-main"><span style="color: Blue;">&lt;?php</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$filename</span><span style="color: Gray;">&nbsp; = </span><span style="color: Blue;">dirname</span><span style="color: Olive;">(</span><span style="color: Green;">__FILE__</span><span style="color: Olive;">)</span><span style="color: Gray;">.</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">/data.txt</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Gray;">;<br />
&nbsp;<br />
&nbsp; </span><span style="color: rgb(255, 165, 0);">// store new message in the file</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$msg</span><span style="color: Gray;"> = </span><span style="color: Green;">isset</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$_GET</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">msg</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">])</span><span style="color: Gray;"> ? </span><span style="color: rgb(0, 0, 139);">$_GET</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">msg</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">]</span><span style="color: Gray;"> : </span><span style="color: rgb(139, 0, 0);">''</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Green;">if</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$msg</span><span style="color: Gray;"> !=  </span><span style="color: rgb(139, 0, 0);">''</span><span style="color: Olive;">)</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">{</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Blue;">file_put_contents</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$filename</span><span style="color: Gray;">,</span><span style="color: rgb(0, 0, 139);">$msg</span><span style="color: Olive;">)</span><span style="color: Gray;">;<br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Green;">die</span><span style="color: Olive;">()</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: rgb(255, 165, 0);">// infinite loop until the data file is not modified</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$lastmodif</span><span style="color: Gray;">&nbsp; &nbsp; = </span><span style="color: Green;">isset</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$_GET</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">timestamp</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">])</span><span style="color: Gray;"> ? </span><span style="color: rgb(0, 0, 139);">$_GET</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">timestamp</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">]</span><span style="color: Gray;"> : </span><span style="color: Maroon;">0</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$currentmodif</span><span style="color: Gray;"> = </span><span style="color: Blue;">filemtime</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$filename</span><span style="color: Olive;">)</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Green;">while</span><span style="color: Gray;"> </span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$currentmodif</span><span style="color: Gray;"> &lt;= </span><span style="color: rgb(0, 0, 139);">$lastmodif</span><span style="color: Olive;">)</span><span style="color: Gray;"> </span><span style="color: rgb(255, 165, 0);">// check if the data file has been  modified</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">{</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Blue;">usleep</span><span style="color: Olive;">(</span><span style="color: Maroon;">10000</span><span style="color: Olive;">)</span><span style="color: Gray;">; </span><span style="color: rgb(255, 165, 0);">//  sleep 10ms to unload the CPU</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Blue;">clearstatcache</span><span style="color: Olive;">()</span><span style="color: Gray;">;<br />
&nbsp;&nbsp; &nbsp;</span><span style="color: rgb(0, 0, 139);">$currentmodif</span><span style="color: Gray;"> = </span><span style="color: Blue;">filemtime</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$filename</span><span style="color: Olive;">)</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Olive;">}</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: rgb(255, 165, 0);">// return a json array</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$response</span><span style="color: Gray;"> = </span><span style="color: Green;">array</span><span style="color: Olive;">()</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$response</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">msg</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">]</span><span style="color: Gray;">&nbsp; &nbsp; &nbsp; &nbsp;= </span><span style="color: Blue;">file_get_contents</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$filename</span><span style="color: Olive;">)</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: rgb(0, 0, 139);">$response</span><span style="color: Olive;">[</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Red;">timestamp</span><span style="color: rgb(139, 0, 0);">'</span><span style="color: Olive;">]</span><span style="color: Gray;"> = </span><span style="color: rgb(0, 0, 139);">$currentmodif</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Green;">echo</span><span style="color: Gray;"> </span><span style="color: Blue;">json_encode</span><span style="color: Olive;">(</span><span style="color: rgb(0, 0, 139);">$response</span><span style="color: Olive;">)</span><span style="color: Gray;">;<br />
&nbsp; </span><span style="color: Blue;">flush</span><span style="color: Olive;">()</span><span style="color: Gray;">;<br />
&nbsp;<br />
&nbsp; </span><span style="color: Blue;">?&gt;</span></div>
</div>
<p>客户端index.html：</p>
<div class="hl-surround">
<div class="hl-main"><span style="color: Olive;">&lt;</span><span style="color: Gray;">!</span><span style="color: rgb(0, 0, 139);">DOCTYPE</span><span style="color: Gray;">  </span><span style="color: rgb(0, 0, 139);">html</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">PUBLIC</span><span style="color: Gray;"> </span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">-//W3C//DTD XHTML 1.1//EN</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">html</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">xmlns</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">http://www.w3.org/1999/xhtml</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">head</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">title</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">Comet demo</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">title</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">meta</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">http-equiv</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">Content-Type</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">content</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">text/html;  charset=utf-8</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">script</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">type</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">text/javascript</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">src</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">prototype.js</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;&lt;/</span><span style="color: Green;">script</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">head</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">body</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">div</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">id</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">content</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">p</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">form</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">action</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">method</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">get</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">onsubmit</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">comet.doRequest($('word').value);$('word').value='';return  false;</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">input</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">type</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">text</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">name</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">word</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">id</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">word</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">value</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp; &nbsp;</span><span style="color: Olive;">&lt;</span><span style="color: Green;">input</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">type</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">submit</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">name</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">submit</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">value</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">Send</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Gray;"> </span><span style="color: Olive;">/&gt;</span><span style="color: Gray;"><br />
&nbsp;&nbsp; &nbsp;</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">form</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">p</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: Olive;">&lt;</span><span style="color: Green;">script</span><span style="color: Gray;"> </span><span style="color: rgb(0, 0, 139);">type</span><span style="color: Gray;">=</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Red;">text/javascript</span><span style="color: rgb(139, 0, 0);">&quot;</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp; var Comet = Class.create();<br />
&nbsp;  Comet.prototype = {<br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp;timestamp: 0,<br />
&nbsp;&nbsp; &nbsp;url:  './backend.php',<br />
&nbsp;&nbsp; &nbsp;noerror: true,<br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp;initialize:  function() { },<br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp;connect: function()<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp;  &nbsp;this.ajax = new Ajax.Request(this.url, {<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;method: 'get',<br />
&nbsp;&nbsp;  &nbsp; &nbsp; &nbsp;parameters: { 'timestamp' : this.timestamp },<br />
&nbsp;&nbsp; &nbsp; &nbsp;  &nbsp;onSuccess: function(transport) {<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// handle the server  response<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var response = transport.responseText.evalJSON();<br />
&nbsp;&nbsp;  &nbsp; &nbsp; &nbsp; &nbsp;this.comet.timestamp = response['timestamp'];<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;  &nbsp;this.comet.handleResponse(response);<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.comet.noerror =  true;<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;},<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;onComplete: function(transport) {<br />
&nbsp;&nbsp; &nbsp;  &nbsp; &nbsp; &nbsp;// send a new ajax request when this request is finished<br />
&nbsp;&nbsp; &nbsp; &nbsp;  &nbsp; &nbsp;if (!this.comet.noerror)<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// if a connection problem  occurs, try to reconnect each 5 seconds<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp;setTimeout(function(){ comet.connect() }, 5000); <br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else<br />
&nbsp;&nbsp;  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.comet.connect();<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.comet.noerror = false;<br />
&nbsp;&nbsp;  &nbsp; &nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp; &nbsp;});<br />
&nbsp;&nbsp; &nbsp; &nbsp;this.ajax.comet = this;<br />
&nbsp;&nbsp; &nbsp;},<br />
&nbsp;<br />
&nbsp;&nbsp;  &nbsp;disconnect: function()<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp;},<br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp;handleResponse:  function(response)<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp; &nbsp;$('content').innerHTML += '</span><span style="color: Olive;">&lt;</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">' +  response['msg'] + '</span><span style="color: Olive;">&lt;/</span><span style="color: Green;">div</span><span style="color: Olive;">&gt;</span><span style="color: Gray;">';<br />
&nbsp;&nbsp; &nbsp;},<br />
&nbsp;<br />
&nbsp;&nbsp; &nbsp;doRequest:  function(request)<br />
&nbsp;&nbsp; &nbsp;{<br />
&nbsp;&nbsp; &nbsp; &nbsp;new Ajax.Request(this.url, {<br />
&nbsp;&nbsp; &nbsp;  &nbsp; &nbsp;method: 'get',<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;parameters: { 'msg' : request <br />
&nbsp;&nbsp; &nbsp;  &nbsp;});<br />
&nbsp;&nbsp; &nbsp;}<br />
&nbsp; }<br />
&nbsp; var comet = new Comet();<br />
&nbsp; comet.connect();<br />
&nbsp;  </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">script</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp;<br />
&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">body</span><span style="color: Olive;">&gt;</span><span style="color: Gray;"><br />
&nbsp; </span><span style="color: Olive;">&lt;/</span><span style="color: Green;">html</span><span style="color: Olive;">&gt;</span></div>
</div>
<p>例子完整源码下载：<span class="download"><a target="_blank" href="/upload/201007/2010071203500842.gz">点击这里下载(tar.gz)</a></span><a href="http://www.zeitoun.net/_media/articles/comet_and_php/comet-ajax.tar.gz"></a></p>
<p>你可以用浏览器打开多个index.html，你在其中一个页面提交的聊天内容同时也被推到其他的页面。<br />
这只是一个推的简单的例子，关于超时处理的相关功能就不贴了，自己研究。</p>
<blockquote>
<p>总之。ajax模拟http长连接就是在第一次ajax发出请求的时候，服务端一直在等待有更新的数据，当然在等待过程中 你可以加入超时重新开始下一个轮询来降低服务器压力(见上面的核心图)。</p>
</blockquote>
<p><strong>参考文章：</strong><br />
<a href="http://www.ibm.com/developerworks/cn/websphere/techjournal/0711_col_burckart/0711_col_burckart.html">Erik  Burckart：Comet 的诱惑</a><br />
<a href="http://www.ibm.com/developerworks/cn/web/wa-lo-comet/">Comet：基于  HTTP 长连接的&ldquo;服务器推&rdquo;技术</a><br />
<a href="http://www.zeitoun.net/articles/comet_and_php/start">How to  implement COMET with PHP</a></p>]]></description>
		<category>网海拾贝</category>
		<guid>http://www.xklog.org/article/internet/comet-ajax-longpoll-push.html</guid>
		<pubDate>Mon, 12 Jul 2010 03:45:00 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[开启Ubuntu的Apache的mod-rewrite]]></title>
		<link>http://www.xklog.org/article/study/Ubuntu-Apache-mod-rewrite.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>Ubuntu默认安装mod_rewrite，但是不自动开启，通过查看apache的配置文件结构，可以实现如下：</p>
<p>把 /etc/apache2/mods-available/rewrite.load 连接到  /etc/apache2/mods-enabled/rewrite.load 来打开 Mod_rewrite 模块。</p>
<p>运行命令： sudo ln -s /etc/apache2/mods-available/rewrite.load  /etc/apache2/mods-enabled/rewrite.load</p>
<p>问题依然没有解决，事实上，当我在 Ubuntu 中采用上述做法并重启了 Apache 服务后，仍然无法正常 rewrite  网址。</p>
<p>这里，还有一点需要注意的地方： 修改 /etc/apache2/sites-available/default中 AllowOverride None 为： AllowOverride All</p>
<p>上面的 /etc/apache2/sites-enabled/000-default 实则为  /etc/apache2/sites-available/default 的连接。而 AllowwOverride None 则会完全忽略  .htaccess 文件，自然其中所定义的 rewrite 规则也就不能生效了。</p>
<p>最后重启 Apache: sudo /etc/init.d/apache2 restart  搞定。</p>]]></description>
		<category>学习笔记</category>
		<guid>http://www.xklog.org/article/study/Ubuntu-Apache-mod-rewrite.html</guid>
		<pubDate>Tue, 06 Jul 2010 19:27:14 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[删除 .SVN 目录]]></title>
		<link>http://www.xklog.org/article/internet/delete-svn-dir.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>在项目开发和日常文档管理时，用到了SVN，由于要把一些文档发给同事，这时想删除SVN版本信息文件，于是上网在SVN中文论坛找到了一份资料： <br />
<br />
删除&nbsp; .svn 文件 <br />
<br />
一、在linux下  <br />
<br />
删除这些目录是很简单的，命令如下  <br />
find . -type d -name &quot;.svn&quot;|xargs rm -rf  <br />
<br />
或者  <br />
<br />
find . -type d -iname &quot;.svn&quot; -exec rm -rf {} \;&nbsp;&nbsp;  <br />
<br />
<br />
二、在windows下用以下法子：  <br />
<br />
1、在项目平级的目录，执行dos命令：  <br />
xcopy project_dir project_dir_1 /s /i  <br />
<br />
2、或者在项目根目录执行以下dos命令  <br />
for /r . %%a in (.) do @if exist &quot;%%a\.svn&quot; rd /s /q &quot;%%a\.svn&quot;  <br />
<br />
其实第二种方法可以用来干很多事的，比如把代码中的.svn替换为任意其他文件名并在硬盘根目录下执行，就可以从硬盘上删除所有的这个文件啦。  <br />
<br />
3、添加注册表(亲自动手测试过)  <br />
可以将&ldquo;快速删除SVN版本信息&rdquo;命名增加到资源管理器的右键上，这样，鼠标点两下就能把选中目录下的所有.svn目录干掉了。 <br />
<br />
代码为：  <br />
<br />
Windows Registry Editor Version 5.00  <br />
<br />
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]  <br />
@=&quot;快速删除SVN版本信息&quot;  <br />
<br />
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]   <br />
@=&quot;cmd.exe /c D:\工具\批处理文件删除SVN版本信息.bat&quot;  <br />
将这段代码保存为一个.reg文件，双击确认导入注册表中不完整，后来自己手工添加。注意：文件&ldquo;批处理文件删除SVN版本信息.bat&rdquo;不能放 在有空格的文件夹下，确认删除时请看一下当前目录不要删除不该删的目录下的SVN版本信息。不知道怎么改进&ldquo;cmd.exe /c  D:\工具\批处理文件删除SVN版本信息.bat&rdquo;。 <br />
<br />
<br />
批处理文件删除SVN版本信息.bat文件内容如下： <br />
@echo off <br />
echo *********************************************************** <br />
echo  清除SVN版本信 息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   <br />
echo *********************************************************** <br />
:start <br />
::启动过程，切换目录 <br />
:set pwd=%cd% <br />
:cd %1 <br />
echo 工作目录是：&amp; chdir <br />
:input <br />
::获取输入，根据输入进行处理 <br />
set source=: <br />
set /p source=确定要清楚当前目录下的.svn信息吗？[Y/N/Q]  <br />
set &quot;source=%source:&quot;=%&quot; <br />
if &quot;%source%&quot;==&quot;y&quot; goto clean  <br />
if &quot;%source%&quot;==&quot;Y&quot; goto clean  <br />
if &quot;%source%&quot;==&quot;n&quot; goto noclean  <br />
if &quot;%source%&quot;==&quot;N&quot; goto noclean  <br />
if &quot;%source%&quot;==&quot;q&quot; goto end <br />
if &quot;%source%&quot;==&quot;Q&quot; goto end <br />
goto input <br />
:clean <br />
::主处理过程，执行清理工作 <br />
@echo on <br />
@for /d /r %%c in (.svn) do @if exist %%c ( rd /s /q %%c &amp;  echo&nbsp;&nbsp;&nbsp; 删除目录%%c) <br />
@echo off <br />
echo &quot;当前目录下的svn信息已清除&quot; <br />
goto end <br />
:noclean <br />
::分支过程，取消清理工作 <br />
echo &quot;svn信息清楚操作已取消&quot; <br />
goto end <br />
:end <br />
::退出程序 <br />
cd &quot;%pwd%&quot; <br />
pause</p>]]></description>
		<category>网海拾贝</category>
		<guid>http://www.xklog.org/article/internet/delete-svn-dir.html</guid>
		<pubDate>Sun, 27 Jun 2010 01:40:51 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[温爷爷路过浙大(zz CC98)]]></title>
		<link>http://www.xklog.org/article/emotion/premier-pass-by-zju.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p><strong>图书馆一楼沸腾了。。温家宝来了。。直播</strong><br />
<span id="ubbcode1">好多好多人。。<br />
温家宝来了。。。太牛 了。。大家快来看看<br />
说道玉树地震和国家洪涝灾害<br />
说我们国家自然灾难深重，唯有科学求实态度才能救助，然后大家鼓掌<br />
说去了杭州阿里巴巴网络中心，谈了一个多钟头，和年轻人谈话很快乐，他忘了嘱咐他们一句话，希望他们要永远快乐，又是鼓掌，希望青年人永远快乐，但同时又要给青年创造<br />
四 点钟才回来，书记省长问总理有安排么，总理说没有，吃过晚饭，总理说要来浙大，他只是惦记，所以来看看，鼓掌<br />
总理说来陪我们聊聊，但是怕打扰我们 学习，大家都说没有，总理说要是聊上几句能多考几分也是好的么。。鼓掌。<br />
谈到浙大校训了。。这段在听。。没有记下来，继续直播<br />
<br />
被 一个保镖盯上了。。没听到。。<br />
谈到学术研究，鼓励我们同学要有无穷的求知的欲望<br />
貌似省长，书记，教育厅厅长，校 长，郑强，来茂德等等重量级全来了。。打量记者。。<br />
总理貌似刚从灾区回来，好辛苦呀。。看上去还是很精神的。。偶刚才跑过去近距离围观，图就不贴 了。反正肯定上新闻。比我拍的好<br />
谈到企业责任，企业要为社会做出自己的贡献。。。我表示我听不太清了。。。<br />
<br />
说我们学校出的名人太 多了，大家要以此而骄傲，貌似总理很了解浙大，说道几个著名校友，开了几个玩笑<br />
<br />
一名大一来自山西的同学提问&ldquo;我们大学生走进社会的机会很 小，请问总理就这方面能提供一些建议和帮助么&rdquo;<br />
总理谈到我们应该多参加暑期实习，然后谈到自身的经历，总理说他学地质的，和竺可桢校长学的差不 多，谈到总理自己的实习的经验，小学的什么，教学实习，毕业实习等等<br />
一名大三的金融的女生问&ldquo;我明年面临毕业，我准备出国，请问总理对我们这些即 将走出校门，或者出国的有什么嘱托&rdquo;<br />
总理回答，谈到今天去农贸市场，遇到一位浙大老师的家属，问了他两个问题，一个是中国经济还不富裕，为什么要 买美国那么多国债，另外一个私人问题，总理没有说出来，于是话题转到了金融<br />
说道一些中国的经济金融问题。。好吧。说的太多。。我打不下来了。。<br />
表 示总理还在图书馆一楼，貌似开始时候说要在这里聊一个小时。。。没有说要不要去青溪之类的。。<br />
现在还是再谈我们国家的外汇储备量（为什么不趁着世 界杯问问中国足球问题，我挤不进去。。要不肯定发问）<br />
再次强调这是浙大一位老师的家属提的问题。。<br />
总理说他还没有回答完呢，说那位女生再 过一两年就要出国了，出国学习，学习金融是非常难得，谈到在某个金融街给别人讲话<br />
总理还在图书馆。。貌似没有结束迹象，大家来图书馆门口围观吧， 总理很辛苦很慈祥，刚从灾区回来还来看望我们。。一直最喜欢总理了。<br />
说道金融危机了，说一些国家高福利，低储蓄，导致金融危机的出现，说到我们国 家面对金融危机的一些措施，深入浅出。<br />
有一个男生问&ldquo;浙大和某些首都大学比还差一点，说由于一些政治因素，说浙大由于这些因素，政界高官很少，说 希望您是我们的校友，我想问，对于像我这样想从政的，像您一样为中国老百姓服务的，您有什么好的建议&rdquo;<br />
总理说，希望浙大也能出一些杰出的人才，包 括政界的，但是这要是人民的政治家<br />
举了个例子，说就是做学问不做官的典型<br />
没听清第四个问题，一个女生，外院的问的。。<br />
貌似是关于 哲学的一个问题<br />
<br />
总理看上去精神还不错，不过貌似有点累哦<br />
大四毕业生，一个女生，&ldquo;就要去美国弗罗里达大学，我很激动，总理是以什 么疯狂的方式结束大学生活&rdquo;<br />
总理说，以实事求是精神，总理谈到自己学地质，总有一种不服气的精神<br />
总理谈到自己毕业本来想去西藏，大家鼓 掌，然后说因为功课好，老师让他去读研究生<br />
我觉得谈话没有结束的意思。。。大家淡定呀。。<br />
<br />
07级国防生提问：&ldquo;说现在和平时期， 很多人缺少国防意识，问总理怎么看，说自己学大气，问总理水灾问题&rdquo;<br />
总理说国防科学很重要<br />
有一个挂牌子的在后头看我发帖。。吓了一跳。。<br />
总 理又谈到哲学问题，说道忧患意识。<br />
换了个人讲话，不知道是谁，结束了，大家围观!!!!!!!!!<br />
强调总理很辛苦，开始往外走了！！<br />
本 来有个好位置，差点强到握手。。。没握到。。呜呜<br />
直播结束。。理科生，非新闻系，疏漏错误在所难免。。谢谢大家围观<br />
<br />
图片明天大家 自己看新闻，详细报道继续看新闻。谢幕啦。。</span></p>]]></description>
		<category>心路历程</category>
		<guid>http://www.xklog.org/article/emotion/premier-pass-by-zju.html</guid>
		<pubDate>Fri, 25 Jun 2010 23:13:37 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[由于忘记给 VPS 续费，博客过去两天无法正常访问]]></title>
		<link>http://www.xklog.org/article/announcements/foget-pay-for-vps.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>RT</p>]]></description>
		<category>本站公告</category>
		<guid>http://www.xklog.org/article/announcements/foget-pay-for-vps.html</guid>
		<pubDate>Sat, 05 Jun 2010 17:41:39 +0000</pubDate>
	</item>

	
	<item>
		<title><![CDATA[Linux下指定文件打包为ISO文件]]></title>
		<link>http://www.xklog.org/article/study/Linux-ISO.html</link>
		<author>星空泪</author>
		<description><![CDATA[<p>1、使用mkisofs，将win98目录下的文件打包为iso镜像文件<br />
mkisofs -o mywin98.iso win98/*&nbsp;</p>
<p>2、 使用 genisoimage，将俄罗斯方块目录下的所有文件打包为tetris.iso文件<br />
genisoimage -o  tetris.iso 俄罗斯方块/*</p>
<p>实际上，mkisofs 是指向genisoimage的一个软连接。</p>]]></description>
		<category>学习笔记</category>
		<guid>http://www.xklog.org/article/study/Linux-ISO.html</guid>
		<pubDate>Sun, 30 May 2010 22:02:50 +0000</pubDate>
	</item>

	</channel>
</rss>