热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Web通信之长连接、长轮询(longpolling)(ZZ)

wiki:http:en.wikipedia.orgwikiPush_technologyhttp:feilong.me201107talk-about-polling-and-l

wiki:http://en.wikipedia.org/wiki/Push_technology

http://feilong.me/2011/07/talk-about-polling-and-long-polling 

  1. 轮询(Polling)是指不管服务器端有没有更新,客户端(通常是指浏览器)都定时的发送请求进行查询,轮询的结果可能是服务器端有新的更新过来,也可能什么也没有,只是返回个空的信息。不管结果如何,客户端处理完后到下一个定时时间点将继续下一轮的轮询。
  2. 推送或叫长连接(Long-Polling)的服务其客户端是不做轮询的,客户端在发起一次请求后立即挂起,一直到服务器端有更新的时候,服务器才会主动推送信息到客户端。 在服务器端有更新并推送信息过来之前这个周期内,客户端不会有新的多余的请求发生,服务器端对此客户端也啥都不用干,只保留最基本的连接信息,一旦服务器有更新将推送给客户端,客户端将相应的做出处理,处理完后再重新发起下一轮请求。

举个例子说明下就很清楚了:

  1. 轮询模式,假设是客户端每2秒轮询一次,那么客户端每2秒就会发送一次请求,相应的服务器端每2秒就要响应这个客户端的一次请求。而实际上服务器端可能1秒钟后就有更新,也可能1分钟后才有更新。对于1秒钟就有更新的,客户端至少会有1秒钟的延时;而1分钟后才有更新的,只有最后一次查询有意义,这一分钟内的轮询其实都是没有必要的,服务器端和客户端均有资源的浪费。
  2. 推送模式,客户端发送一次请求后马上挂起等待服务器端响应,可能1秒,也可能10秒钟,也可能1分钟。如果服务器端是1秒就有更新,那么到1秒钟时客户端马上就收到更新了,如果是1分钟才有更新,那么整个一分钟客户端也只请求一次,服务器也只会相应一次,这个跟轮询的区别是不是已经很清楚了。

 

http://www.cnblogs.com/AloneSword/p/3517463.html

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性。

   

一、什么是长连接、长轮询?

用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息。这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已。

 

 

 

二、长连接、长轮询的应用场景

长连接、长轮询一般应用与WebIM、ChatRoom和一些需要及时交互的网站应用中。其真实案例有:WebQQ、Hi网页版、Facebook IM等。

如果你对服务器端的反向Ajax感兴趣,可以参考这篇文章 DWR 反向Ajax 服务器端推的方式:http://www.cnblogs.com/hoojo/category/276235.html

  

三、优缺点

轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。 
优点:后端程序编写比较容易。 
缺点:请求中有大半是无用,浪费带宽和服务器资源。 
实例:适于小型应用。


长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。 
优点:在无消息的情况下不会频繁的请求,耗费资源小。 
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。 
实例:WebQQ、Hi网页版、Facebook IM。

 

长连接:在页面里嵌入一个隐蔵iframe,将这个隐蔵iframe的src属性设为对一个长连接的请求或是采用xhr请求,服务器端就能源源不断地往客户端输入数据。 
优点:消息即时到达,不发无用请求;管理起来也相对方便。 
缺点:服务器维护一个长连接会增加开销。 
实例:Gmail聊天


Flash Socket:在页面中内嵌入一个使用了Socket类的 Flash 程序Javascript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,Javascript在收到服务器端传送的信息后控制页面的显示。 
优点:实现真正的即时通信,而不是伪即时。 
缺点:客户端必须安装Flash插件;非HTTP协议,无法自动穿越防火墙。 
实例:网络互动游戏。

 

 

 

四、实现原理

所谓长连接,就是要在客户端与服务器之间创建和保持稳定可靠的连接。其实它是一种很早就存在的技术,但是由于浏览器技术的发展比较缓慢,没有为这种机制的实现提供很好的支持。所以要达到这种效果,需要客户端和服务器的程序共同配合来完成。通常的做法是,在服务器的程序中加入一个死循环,在循环中监测数据的变动。当发现新数据时,立即将其输出给浏览器并断开连接,浏览器在收到数据后,再次发起请求以进入下一个周期,这就是常说的长轮询(long-polling)方式。如下图所示,它通常包含以下几个关键过程:

image

1. 轮询的建立 
建立轮询的过程很简单,浏览器发起请求后进入循环等待状态,此时由于服务器还未做出应答,所以HTTP也一直处于连接状态中。 
2. 数据的推送 
在循环过程中,服务器程序对数据变动进行监控,如发现更新,将该信息输出给浏览器,随即断开连接,完成应答过程,实现“服务器推”。 
3. 轮询的终止 
轮询可能在以下3种情况时终止: 
  3.1. 有新数据推送 
   当循环过程中服务器向浏览器推送信息后,应该主动结束程序运行从而让连接断开,这样浏览器才能及时收到数据。 
  3.2. 没有新数据推送 
   循环不能一直持续下去,应该设定一个最长时限,避免WEB服务器超时(Timeout),若一直没有新信息,服务器应主动向浏览器发送本次轮询无新信息的正常响应,并断开连接,这也被称为“心跳”信息。 
  3.3. 网络故障或异常 
   由于网络故障等因素造成的请求超时或出错也可能导致轮询的意外中断,此时浏览器将收到错误信息。 
4. 轮询的重建 
浏览器收到回复并进行相应处理后,应马上重新发起请求,开始一个新的轮询周期。

 

 

 

五、程序设计

1、普通轮询 Ajax方式

客户端代码片段

 

<%&#64; page language&#61;"java" import&#61;"java.util.*" pageEncoding&#61;"UTF-8" isELIgnored&#61;"false" %>

<%&#64; include file&#61;"/tags/jquery-lib.jsp"%>

 

客户端实现的就是用一种普通轮询的结果&#xff0c;比较简单。利用setInterval不间断的刷新来获取服务器的资源&#xff0c;这种方式的优点就是简单、及时。缺点是链接多数是无效重复的&#xff1b;响应的结果没有顺序&#xff08;因为是异步请求&#xff0c;当发送的请求没有返回结果的时候&#xff0c;后面的请求又被发送。而此时如果后面的请求比前面的请求要先返回结果&#xff0c;那么当前面的请求返回结果数据时已经是过时无效的数据了&#xff09;&#xff1b;请求多&#xff0c;难于维护、浪费服务器和网络资源。

 

服务器端代码

 

 

&#64;RequestMapping("/ajax")

public void ajax(long timed, HttpServletResponse response) throws Exception {

PrintWriter writer &#61; response.getWriter();

Random rand &#61; new Random();

// 死循环 查询有无数据变化

while (true) {

Thread.sleep(300); // 休眠300毫秒&#xff0c;模拟处理业务等

int i &#61; rand.nextInt(100); // 产生一个0-100之间的随机数

if (i > 20 && i <56) { // 如果随机数在20-56之间就视为有效数据&#xff0c;模拟数据发生变化

long responseTime &#61; System.currentTimeMillis();

// 返回数据信息&#xff0c;请求时间、返回数据时间、耗时

writer.print("result: " &#43; i &#43; ", response time: " &#43; responseTime &#43; ", request time: " &#43; timed &#43; ", use time: " &#43; (responseTime - timed));

break; // 跳出循环&#xff0c;返回数据

} else { // 模拟没有数据变化&#xff0c;将休眠 hold住连接

Thread.sleep(1300);

}

}

}

 

 

服务器端实现&#xff0c;这里就模拟下程序监控数据的变化。上面代码属于SpringMVC 中controller中的一个方法&#xff0c;相当于Servlet中的一个doPost/doGet方法。如果没有程序环境适应servlet即可&#xff0c;将方法体中的代码copy到servlet的doGet/doPost中即可。

 

服务器端在进行长连接的程序设计时&#xff0c;要注意以下几点&#xff1a; 
1. 服务器程序对轮询的可控性
 
由于轮询是用死循环的方式实现的&#xff0c;所以在算法上要保证程序对何时退出循环有完全的控制能力&#xff0c;避免进入死循环而耗尽服务器资源。 
2. 合理选择“心跳”频率 
从图1可以看出&#xff0c;长连接必须由客户端不停地进行请求来维持&#xff0c;所以在客户端和服务器间保持正常的“心跳”至为关键&#xff0c;参数POLLING_LIFE应小于WEB服务器的超时时间&#xff0c;一般建议在10&#xff5e;20秒左右。 
3. 网络因素的影响 
在实际应用时&#xff0c;从服务器做出应答&#xff0c;到下一次循环的建立&#xff0c;是有时间延迟的&#xff0c;延迟时间的长短受网络传输等多种因素影响&#xff0c;在这段时间内&#xff0c;长连接处于暂时断开的空档&#xff0c;如果恰好有数据在这段时间内发生变动&#xff0c;服务器是无法立即进行推送的&#xff0c;所以&#xff0c;在算法设计上要注意解决由于延迟可能造成的数据丢失问题。 
4. 服务器的性能 
在长连接应用中&#xff0c;服务器与每个客户端实例都保持一个持久的连接&#xff0c;这将消耗大量服务器资源&#xff0c;特别是在一些大型应用系统中更是如此&#xff0c;大量并发的长连接有可能导致新的请求被阻塞甚至系统崩溃&#xff0c;所以&#xff0c;在进行程序设计时应特别注意算法的优化和改进&#xff0c;必要时还需要考虑服务器的负载均衡和集群技术。

image

上图是返回的结果&#xff0c;可以看到先发出请求&#xff0c;不一定会最先返回结果。这样就不能保证顺序&#xff0c;造成脏数据或无用的连接请求。可见对服务器或网络的资源浪费。

 

2、普通轮询 iframe方式

 

<%&#64; page language&#61;"java" import&#61;"java.util.*" pageEncoding&#61;"UTF-8" isELIgnored&#61;"false" %>

<%&#64; include file&#61;"/tags/jquery-lib.jsp"%>

 

这里的客户端程序是利用隐藏的iframe向服务器端不停的拉取数据&#xff0c;将iframe获取后的数据填充到页面中即可。同ajax实现的基本原理一样&#xff0c;唯一不同的是当一个请求没有响应返回数据的情况下&#xff0c;下一个请求也将开始&#xff0c;这时候前面的请求将被停止。如果要使程序和上面的ajax请求一样也可以办到&#xff0c;那就是给每个请求分配一个独立的iframe即可。下面是返回的结果&#xff1a;

image

其中红色是没有成功返回请求就被停止&#xff08;后面请求开始&#xff09;掉的请求&#xff0c;黑色是成功返回数据的请求。

 

3、长连接iframe方式

 

<%&#64; page language&#61;"java" import&#61;"java.util.*" pageEncoding&#61;"UTF-8" isELIgnored&#61;"false" %>

<%&#64; include file&#61;"/tags/jquery-lib.jsp"%>

 

 

这个轮询方式就是把刚才上面的稍微改下&#xff0c;每个请求都有自己独立的一个iframe&#xff0c;当这个iframe得到响应的数据后就把数据push到当前页面上。使用此方法已经类似于ajax的异步交互了&#xff0c;这种方法也是不能保证顺序的、比较耗费资源、而且总是有一个加载的条在地址栏或状态栏附件&#xff08;当然要解决可以利用htmlfile&#xff0c;Google的攻城师们已经做到了&#xff0c;网上也有封装好的lib库&#xff09;&#xff0c;但客户端实现起来比较简单。

 image

如果要保证有序&#xff0c;可以不使用setInterval&#xff0c;将创建iframe的方法放在load事件中即可&#xff0c;即使用递归方式。调整后的代码片段如下&#xff1a;

 

 

 

 

 

 

 

 

 

这种方式虽然保证了请求的顺序&#xff0c;但是它不会处理请求延时的错误或是说很长时间没有返回结果的请求&#xff0c;它会一直等到返回请求后才能创建下一个iframe请求&#xff0c;总会和服务器保持一个连接。和以上轮询比较&#xff0c;缺点就是消息不及时&#xff0c;但保证了请求的顺序。

 

4、ajax实现长连接

 

<%&#64; page language&#61;"java" import&#61;"java.util.*" pageEncoding&#61;"UTF-8" isELIgnored&#61;"false" %>

<%&#64; include file&#61;"/tags/jquery-lib.jsp"%>

 

上面这段代码就是才有Ajax的方式完成长连接&#xff0c;主要优点就是和服务器始终保持一个连接。如果当前连接请求成功后&#xff0c;将更新数据并且继续创建一个新的连接和服务器保持联系。如果连接超时或发生异常&#xff0c;这个时候程序也会创建一个新连接继续请求。这样就大大节省了服务器和网络资源&#xff0c;提高了程序的性能&#xff0c;从而也保证了程序的顺序。

image

 

六、总结

现代的浏览器都支持跨域资源共享&#xff08;Cross-Origin Resource Share&#xff0c;CORS&#xff09;规范&#xff0c;该规范允许XHR执行跨域请求&#xff0c;因此基于脚本的和基于iframe的技术已成为了一种过时的需要。

把Comet做为反向Ajax的实现和使用的最好方式是通过XMLHttpRequest对象&#xff0c;该做法提供了一个真正的连接句柄和错误处理。当然你选择经由HTTP长轮询使用XMLHttpRequest对象&#xff08;在服务器端挂起的一个简单的Ajax请求&#xff09;的Comet模式&#xff0c;所有支持Ajax的浏览器也都支持该种做法。

基于HTTP的长连接技术&#xff0c;是目前在纯浏览器环境下进行即时交互类应用开发的理想选择&#xff0c;随着浏览器的快速发展&#xff0c;html5将为其提供更好的支持和更广泛的应用。在html5中有一个websocket 可以很友好的完成长连接这一技术&#xff0c;网上也有相关方面的资料&#xff0c;这里也就不再做过多介绍。


转:https://www.cnblogs.com/sure/p/3808839.html



推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • DSP中cmd文件的命令文件组成及其作用
    本文介绍了DSP中cmd文件的命令文件的组成和作用,包括链接器配置文件的存放链接器配置信息、命令文件的组成、MEMORY和SECTIONS两个伪指令的使用、CMD分配ROM和RAM空间的目的以及MEMORY指定芯片的ROM和RAM大小和划分区间的方法。同时强调了根据不同芯片进行修改的必要性,以适应不同芯片的存储用户程序的需求。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
author-avatar
美美2012的小幸福
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有