1、HTTP 是无状态、单向的协议,用户只能够通过客服端向服务器发送请求并由服务器处理发回一个响应。若要实现聊天室、WEBQQ、在线客服、邮箱等这些即时通讯的应用,就要用到“ 服务器推送技术(Comet)” 。传统的 AJAX 轮询方式,客服端以用户定义的时间间隔去服务器上查询最新的数据。种这种拉取数据的方式需要很短的时间间隔才能保证数据的精确度,但太短的时间间隔客服端会对服务器在短时间内发送出多个请求。反转 AJAX,就是所谓的长轮询或者 COMET。服务器与客服端需要保持一条长时间的请求,它使得服务器在有数据时可以返回消息给客户端。html:view plaincopy to clipboar
2、dprint?1. 2. javascript:这里使用 AJAX 请求 data.php 页面获得success的值,请求的时间达到 80 秒。在这 80 秒中若没有从服务端返回success则一直保持连接状态,直到有数据返回或 success的值为 0 才关闭连接。在关闭连接后在继续下一次的请求。view plaincopy to clipboardprint?1. $(function() 2. 3. 4. $(“#btn“).bind(“click“,btn:$(“#btn“),function(evdata) 5. $.ajax( 6. type:“POST“, 7. dataTyp
3、e:“json“, 8. url:“data.php“, 9. timeout:80000, /ajax 请求超时时间 80 秒 10. data:time:“80“, /40 秒后无论结果服务器都返回数据 11. success:function(data,textStatus) 12. /从服务器得到数据,显示数据并继续查询 13. if(data.success=“1“) 14. $(“#msg“).append(“有数据“+data.text); 15. evdata.data.btn.click(); 16. 17. /未从服务器得到数据,继续查询 18. if(data.succe
4、ss=“0“) 19. $(“#msg“).append(“无数据“); 20. evdata.data.btn.click(); 21. 22. , 23. /Ajax 请求超时,继续查询 24. error:function(XMLHttpRequest,textStatus,errorThrown) 25. if(textStatus=“timeout“) 26. $(“#msg“).append(“超时“); 27. evdata.data.btn.click(); 28. 29. 30. 31. ); 32. ); 33. 34.); PHP:在这里是无限的循环,循环的结束条件就是获
5、取到了返回结果返回 Json 数据。并且接受$_POSTtime参数来限制循环的超时时间,避免资源的过度浪费。(浏览器关闭不会发消息给服务器,使用可能一直循环下去)view plaincopy to clipboardprint?1. if(empty($_POSTtime)exit(); 2. set_time_limit(0);/无限请求超时时间 3. $i=0; 4. while (true) 5. /sleep(1); 6. usleep(500000);/0.5 秒 7. $i+; 8. 9. /若得到数据则马上返回数据给客服端,并结束本次请求 10. $rand=rand(1,99
6、9); 11. if($rand“1“,name=xiaocai,text=$rand); 13. echo json_encode($arr); 14. exit(); 15. 16. 17. /服务器($_POSTtime*0.5)秒后告诉客服端无数据 18. if($i=$_POSTtime) 19. $arr=array(success=“0“,name=xiaocai,text=$rand); 20. echo json_encode($arr); 21. exit(); 22. 23. 24. 运行效果:在图中可以看到无数据的请求时间达到了 40S,在 40S 的请求中若获得数据则
7、请求关闭。传统的 AJAX 轮询方式:HTTP 请求和响应头信息开销总共包括 871 字节,而且还不包括任何数据,当然,这只是一个例子,你的消息头数据完全可能低于 871 字节,但我也看到过消息头数据超过 2000 字节的情况。在这个例子中,股票主题消息数据大约只有 20 个字符。当你把这样的程序大规模部署给用户时会怎么样?我们使用三个不同的用例观察一下该轮询应用程序关联的 HTTP 请求和响应头数据需要的网络吞吐量。用例 A: 1000 客户端,每秒轮询一次网络吞吐量(871x1000)=871000 字节=6968000 比特/秒(6.6Mbps)用例 B:10000 客户端,每秒轮询一次网络吞吐量(871x10000)=8710000 字节=69680000 比特/秒(66Mbps)用例 C: 100000 客户端,每秒轮询一次网络吞吐量(871x100000)=87100000 字节=696800000 比特/秒(665Mbps)