用简单的程序理解 Polling 与 Long Polling

服务端推送技术应用越来越普遍,应用范围也越来越宽广,技术解决方案也越来越成熟且丰富。很多SNS网站的chat功能就有用到了Long Polling技术。比如fackebook。

Long Polling 原理其实很简单,也很讨巧。与Polling相比,Long Polling客户端也许不会马上收到来自服务端的响应,需要等待一些时间(直到有新消息,或者连接timeout了等等)。同样的,客户端也不再需要定时向服务发送请求了,而是直到收到服务端响应之后,或者连接丢失之后,客户端接着马上请求客户端。

这里,我打个比方,传统的Polling一般是由C向S询问:“有我的信件吗?”。S接到询问之后,会立即查询,并且把查询结果告诉C,不管有没有C的信件,要么回复:“嗯,你有X封信。”,要么回复:“没,没有你的信”。

而Long Polling更像是这样,C向S发出询问:“有我的信件吗?”,S开始查询,如果有则回复C:“嗯,有你x封信”。如果没有,则不作任何回复,而是让C等着,自己一遍一遍地查询是否有订阅者的信。

换句话说:当S收到C的查询请求之后,Polling则只查询一次,并且把查询结果告诉C;而Long Polling收到请求之后,则会一遍一遍地查询,直到有消息才会响应C,不然一直hold Client。

Long Polling相较传统的Polling而言,最大的实惠在于:减少了请求次数。举个例子,假定一个用户每2小时内,有可能收到2条新消息。如果采用传通的Polling方式,每30秒发向服务端发送一次查询请求的话。则在这2小时内,服务器需要处理240(60602/30)次请求,其中至少有238次请求是没有实际意义的。试想,如果是10000的并发量的话,这种浪费是很惊人的。相较而方,Long Polling没有那么浪费服务器资源来处理这些没有实际意义的请求。

Polling

传统的Polling实现方式比较单一,由客户端javascript脚本定时发送http请求。服务端脚本如下:

header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
header("Cache-Control: store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", FALSE);
 
$msg = get_msg();
if ($msg) {
    echo $msg;
} 
else {
    echo '0';
}

上面是一个传统polling简单的服务端脚本。很简单,收到客户端请求后,服务端马上执行脚本查询,并且立即响应客户端。客户端等待的时间很短,客户端唯一要做的事情就是定时向服务端发出查询请求。下面是请求时,通过tcpdump抓到的包:

1>17:49:03.533760 IP 192.168.0.98.4383 > devhome.http: S 3235664319:3235664319(0) win 65535 <mss 1460,nop,nop,sackOK>
2>17:49:03.534336 IP devhome.http > 192.168.0.98.4383: S 2018732723:2018732723(0) ack 3235664320 win 5840 <mss 1460,nop,nop,sackOK>
3>17:49:03.533841 IP 192.168.0.98.4383 > devhome.http: . ack 1 win 65535
4>17:49:03.534404 IP 192.168.0.98.4383 > devhome.http: P 1:781(780) ack 1 win 65535
5>17:49:03.534416 IP devhome.http > 192.168.0.98.4383: . ack 781 win 7020
6>17:49:03.535033 IP devhome.http > 192.168.0.98.4383: P 1:369(368) ack 781 win 7020
7>17:49:03.535110 IP devhome.http > 192.168.0.98.4383: F 369:369(0) ack 781 win 7020
8>17:49:03.535263 IP 192.168.0.98.4383 > devhome.http: . ack 370 win 65167
9>17:49:03.536105 IP 192.168.0.98.4383 > devhome.http: F 781:781(0) ack 370 win 65167
10>17:49:03.536111 IP devhome.http > 192.168.0.98.4383: . ack 782 win 7020
  • 第1、2、3行,TCP三次握手,建立连接。

  • 第4行,由192.168.0.98向服务端devhome发送httpd请求。

  • 第5行,由服务端devhome确认收到了来自客户端192.168.0.98的http请求。

  • 第6行,服务器响devhom响应客户端192.168.0.98刚才发的httpd请求。注意:特别注意一下第一列时间截,http请求与http响应的时间间隔很短,才0.001s

  • 第7、8、9、10共4行,TCP四次挥手,断开连接。由服务端主动断开连接。

  • Long Polling
    Long Polling较之Polling稍微有些不一样,Long Polling持续执行,以此延迟对客户端的响应。请查看代码:

header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
header("Last-Modified: ". gmdate("D, d M Y H:i:s") ." GMT");
header("Cache-Control: store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", FALSE);
//在$timeout之后,关闭连接,并且要求客户3秒后重新请求
for ($i = 0, $timeout = 60; $i < $timeout; $i++ ) {
 $msg = get_msg();
 if ($msg) {
     echo json_encode(array('t' => 'info' , 'c' => $msg));
     flush();
     exit(0);
 }  
 usleep(3000000);
}
echo json_encode(array('t' => 'refresh', 'c' => 3000));
flush();

上面是Long Polling服务端代码。语意也很明了,如果有$msg,则会马上响应客户端请求,并且关闭该TCP连接。如果在$timeout之内,没有$msg,则会让客户端一直保持该TCP连接,不中断(关闭)。直到超过了$timeout(具体时间主要取决于$timeout * $usleep_time),服务端会要求客户端重新请求(重新建立TCP连接),同时关闭当前TCP连接。下面是通过 tcpdump抓到的包:

1>18:39:46.449563 IP 192.168.0.98.4407 > devhome.http: S 174149200:174149200(0) win 65535 <mss 1460,nop,nop,sackOK>
2>18:39:46.449587 IP devhome.http > 192.168.0.98.4407: S 938669730:938669730(0) ack 174149201 win 5840 <mss 1460,nop,nop,sackOK>
3>18:39:46.449692 IP 192.168.0.98.4407 > devhome.http: . ack 1 win 65535
4>18:39:46.450308 IP 192.168.0.98.4407 > devhome.http: P 1:793(792) ack 1 win 65535
5>18:39:46.450320 IP devhome.http > 192.168.0.98.4407: . ack 793 win 7128
6>18:42:46.521749 IP devhome.http > 192.168.0.98.4407: P 1:377(376) ack 793 win 7128
7>18:42:46.521825 IP devhome.http > 192.168.0.98.4407: P 377:412(35) ack 793 win 7128
8>18:42:46.521859 IP devhome.http > 192.168.0.98.4407: F 412:412(0) ack 793 win 7128
9>18:42:46.521997 IP 192.168.0.98.4407 > devhome.http: . ack 412 win 65124
10>18:42:46.522021 IP 192.168.0.98.4407 > devhome.http: . ack 413 win 65124
11>18:42:46.522965 IP 192.168.0.98.4407 > devhome.http: F 793:793(0) ack 413 win 65124
12>18:42:46.522970 IP devhome.http > 192.168.0.98.4407: . ack 794 win 7128
  • 第1、2、3行,TCP三次握手,建立连接。
  • 第4行,由192.168.0.98向服务端192.168.0.6发送http请求。
  • 第5行,由192.168.0.6确认收到192.168.0.98刚刚发送的请求。
  • 第6、7行,服务器host_6响应3分钟前客户端192.168.0.98发出的http请求。注意,第一列的时间截,第5与第6行之差为3分钟。这与服务端脚本,客户端监控是相呼应的。
  • 最后4行,TCP四次挥手,断开连接,同样由服务端devhome发起。

响应客户端host_98的http请求,在3分钟之后。这也说明了,Long Polling与Polling的区别在于,客户端有可能需要等待更长时间才能收到服务端的响应。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容