加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flex+PHP反向推送(长轮询)

发布时间:2020-12-15 03:39:43 所属栏目:百科 来源:网络整理
导读:反向推送技术现在非常流行,而长轮询是实现反向推送的关键技术之一. //如果要轉載本文請注明出處,免的出現版權紛爭,我不喜歡看到那種轉載了我的作品卻不注明出處的人 Seven{See7di#Gmail.com} HTTP 协议的成功毋庸置疑。它是 Internet上大部分信息交换的基

反向推送技术现在非常流行,而长轮询是实现反向推送的关键技术之一.

//如果要轉載本文請注明出處,免的出現版權紛爭,我不喜歡看到那種轉載了我的作品卻不注明出處的人 Seven{See7di#Gmail.com}
HTTP 协议的成功毋庸置疑。它是 Internet上大部分信息交换的基础。然而,它也有一些局限性。特别是,它是无状态、单向的协议。请求被发送到 Web 服务器,服务器处理请求并发回一个响应 —仅此而已。请求必须由客户机发出,而服务器则只能在对请求的响应中发送数据。这至少会影响很多类型的 Web应用程序的实用性。典型的例子就是聊天程序。另外还有一些例子,例如比赛的比分或电子邮件程序。

HTTP的这些局限性也是它取得一定成功的原因。请求/响应周期使它成为了经典的模型,即每个连接使用一个线程。只要能够快速为请求提供服务,这种方法就 有巨大的可伸缩性。每秒钟可以处理大量的请求,只需使用少量的服务器就可以处理很大数量的用户。对于很多经典的 Web应用程序,例如内容管理系统、搜索应用程序和电子商务站 点等等而言,这非常适合。在以上任何一种 Web应用程序中,服务器提供用户请求的数据,然后关闭连接,并释放那个线程,使之可以为其他请求服务。如果提供初始数据之后仍可能存在交互,那么将连接 保持为打开状态,因此线程就不能释放出来,服务器也就不能为很多用户服务。

但是,如果想在对请求做出响应并发送初始数据之后,仍然保持与用户的交互呢?在 Web 早期,这一点常使用 meta刷新实现。这将自动指示浏览器在指定秒数之后重新装载页面,从而支持简陋的轮询(polling)。这不仅是一种糟糕的用户体验,而且通常效率非 常低下。如果没有新的数据要显示在页面上呢?这时不得不重新呈现同样的页面。如果对页面的更改很少,并且页面的大部分没有变化呢?同样,不管是否有必要, 都得重新请求和获取页面上的一切内容。

Ajax 的发明和流行改变了上述状况。现在,服务器可以异步通信,因此不必重新请求整个页面。现在可以进行增量式的更新。只需使用XMLHttpRequest 轮询服务器。这项技术通常被称作Comet。这项技术存在一些变体,每种变体具有不同的性能和可伸缩性。我们来看看这些不同风格的 Comet。

Comet 风格

Ajax 的出现使 Comet 成为可能。HTTP的单向性质可以有效地加以规避。实际上有一些不同的方法可以绕过这一点。您可能已经猜到,支持 Comet 的最容易的方式是轮询(poll)。使用XMLHttpRequest 向服务器发出调用,返回后,等待一段固定的时间(通常使用 JavaScript 的 setTimeout函数),然后再次调用。这是一项非常常见的技术。例如,大多数 webmail 应用程序就是通过这种技术在电子邮件到达时显示电子邮件的。

这项技术有优点也有缺点。在这种情况下,您期望快速返回响应,就像任何其他 Ajax请求一样。在请求之间必须有一段暂停。否则,连续不断的请求会冲垮服务器,并且这种情况下显然不具有可伸缩性。这段暂停使应用程序产生一个延时。 暂停的时间越长,服务器上的新数据就需要越多的时间才能到达客户机。如果缩短暂停时间,又将重新面临冲垮服务器的风险。但是另一方面,这显然是最简单的实 现Comet 的方式。

现在应该指出,很多人认为轮询并不属于 Comet。相反,他们认为 Comet 是对轮询的局限性的一个解决方 案。最常见的 “真正的”Comet 技术是轮询的一种变体,即长轮询(longpolling)。轮询与长轮询之间的主要区别在于服务器花多长的时间作出响应。长轮询通常将连接保持一段较长 的时间 —通常是数秒钟,但是也可能是一分钟甚至更长。当服务器上发生某个事件时,响应被发送并随即关闭,轮询立即重新开始。

长轮询相对于一般轮询的优点在于,数据一旦可用,便立即从服务器发送到客户机。请求可能等待较长的时间,期间没有任何数据返回,但是一旦有了新的数据,它 将立即被发送到客户机。因此没有延时。如果您使用过基于 Web 的聊天程序,或者声称 “实时” 的任何程序,那么它很可能就是使用了这种技术。

下面我就Flex和PHP来举例说明一下,常轮询如何实现.


首先将一下PHP端的代码,很简单?

<?php//timeout in seconds$timeout = 60;// log start time$start_time = time();// get messge from local filefunction get_msg(){??? return file_get_contents('msg.txt');}// get message$last_msg = get_msg();// start the loopwhile (true){??? // get current time??? $current_time = time();?? ???? // check if we are timed out??? if ($current_time - $start_time > $timeout){??????? echo 'timeout! no new message!';??????? break;??? }?? ???? // get latest message??? $current_msg = get_msg();?? ???? // check if the message has been changed??? if ($last_msg != $current_msg){??????? echo $current_msg;??????? break;??? }??? // sleep 1 sec??? sleep(1);}分析上面的代码,其实原理就是在php中执行一个循环,每次循环的时候去访问服务器上的数据,可以是数据库也可以是一个文本文件,这里采用文本文件,然后判断文本文件的内容是否更新过,如果更新过则将数据返回给客户端. 在循环当中我们放入了 sleep(1)函数让代码每次循环的时候暂停1秒钟,这样不至于过度损耗服务器CPU的资源. 下面是flex端的代码

<?xml version="1.0" encoding="utf-8"?> ??????? <![CDATA[ ??????????? // request object ??????????? private var req:URLRequest; ?????????? ? ??????????? // loader object ??????????? private var loader:URLLoader; ?????????? ? ??????????? // timer ??????????? private var timer:Timer; ?????????? ? ??????????? [Bindable] ??????????? private var count:Number = 0;?????????? ? ?????????? ? ??????????? // do some initializing ??????????? private function init():void{ ??????????????? req = new URLRequest('http://127.0.0.1:8080/long_polling.php'); ??????????????? loader = new URLLoader(); ?????????????? ? ??????????????? loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,onStatusChange); ??????????????? loader.addEventListener(Event.COMPLETE,onComplete); ??????????????? loader.addEventListener(IOErrorEvent.IO_ERROR,onIOError); ?????????????? ? ??????????????? timer = new Timer(1000); ??????????????? timer.addEventListener(TimerEvent.TIMER,onTimer,false,true); ?????????????? ? ??????????? } ?????????? ? ??????????? // update the second count ??????????? private function onTimer(event:TimerEvent):void{ ??????????????? count ++; ??????????? } ?????????? ? ??????????? // start the request ??????????? private function startRequest():void{ ??????????????? count = 0; ??????????????? loader.load(req); ??????????????? timer.start(); ??????????????? this.txtLogs.text += 'Request started!n'; ??????????? } ?????????? ? ??????????? // status changed ??????????? private function onStatusChange(event:HTTPStatusEvent):void{ ??????????????? this.txtLogs.text += 'Status changed to '+ String(event.status)+'n'; ??????????? }?????????? ? ?????????? ? ??????????? // result returned ??????????? private function onComplete(event:Event):void{ ??????????????? this.txtLogs.text += 'Completed! Result is '+String(event.currentTarget.data)+'n'; ??????????????? this.txtLogs.text += 'Start another request!n'; ??????????????? this.startRequest(); ??????????? } ?????????? ? ??????????? // error handler ??????????? private function onIOError(event:IOErrorEvent):void{ ??????????????? this.txtLogs.text += 'IO Error: '+String(event)+'n'; ??????????????? this.stopRequest(); ??????????? } ?????????? ? ??????????? // stop the request ??????????? private function stopRequest():void{ ??????????????? count = 0; ??????????????? this.txtLogs.text += 'Request stopped!n'; ??????????????? this.txtLogs.text += '<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>n' ??????????????? this.timer.stop(); ??????????????? this.loader.close(); ?????????????? ? ??????????? } ??????? ]]> 我们新建一个flex项目,然后在界面上放置4个空间,两个按钮,一个是开始请求,一个是结束请求,还有一个label用来显示当前请求所花的时间,最后再放一个TextArea来显示log. 请求的原理也同样简单,通过URLLoader和URLRequest来实现,和普通的http请求并无两样.不过在一次请求获取到结果的时候(走到onComplete()函数),我们需要重新开始另外一次查询,通过这种方式我们就可以模拟出一个类似与C/S架构的网络连接,而服务端上的任何更新则会自动推送到客户端了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读