android轮询机制微信是长连接还是轮询

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&Pages: 1/2
主题 : 请教关于长连接,轮询要怎么做呀?
级别: 侠客
UID: 51828
可可豆: 312 CB
威望: 301 点
在线时间: 165(时)
发自: Web Page
请教关于长连接,轮询要怎么做呀?&&&
现在遇到一个问题,请求服务器一个地址一直保持请求状态,如果服务器有返回JASON就处理,没有的话,就一直保持着,请教大神们,要怎么做呀?
级别: 侠客
UID: 127920
可可豆: 37 CB
威望: 456 点
在线时间: 152(时)
发自: Web Page
runLoop?分线程运行时判断?没做过,但认为这是一个思路
级别: 侠客
UID: 51828
可可豆: 312 CB
威望: 301 点
在线时间: 165(时)
发自: Web Page
回 1楼(azuspace) 的帖子
网上找到了这个代码,但不是很灵光- (void) longPoll {&&&&//create an autorelease pool for the thread&&&&NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];&&&&&&&&//compose the request&&&&NSError* error =&&&&NSURLResponse* response =&&&&NSURL* requestUrl = [NSURL URLWithString:@&http://192.168.100.125/comet/index.html&];&&&&NSURLRequest* request = [NSURLRequest requestWithURL:requestUrl];&&&&&&&&//send the request (will block until a response comes back)&&&&NSData* responseData = [NSURLConnection sendSynchronousRequest:request&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& returningResponse:&response error:&error];&&&&&&&&//pass the response on to the handler (can also check for errors here, if you want)&&&&[self performSelectorOnMainThread:@selector(dataReceived:)&&&&&&&&&&&&&&&&&&&&&&&&&& withObject:responseData waitUntilDone:YES];&&&&//clear the pool&&&&[pool drain];&&&&&&&&//send the next poll request&&&&[self performSelectorInBackground:@selector(longPoll) withObject: nil];}- (void) startPoll {&&&&//not covered in this example:&&stopping the poll or ensuring that only 1 poll is active at any given time&&&&[self performSelectorInBackground:@selector(longPoll) withObject: nil];}- (void) dataReceived: (NSData*) theData {&&&&//process the response here&&&&NSString* aS&&&&aStr = [[NSString alloc] initWithData:theData encoding:NSASCIIStringEncoding];&&&&FVLog(@&aStr=%@&,aStr);}
级别: 精灵王
UID: 92676
发帖: 1014
可可豆: 2272 CB
威望: 2386 点
在线时间: 1139(时)
发自: Web Page
目前我是用定时器做的,很蛋疼。感觉不科学,同求好方法。
级别: 论坛版主
发帖: 2436
可可豆: 174999 CB
威望: 173705 点
在线时间: 5541(时)
发自: Web Page
底层socket.....
级别: 骑士
可可豆: 571 CB
威望: 486 点
在线时间: 339(时)
发自: Web Page
TCP应该行。
级别: 新手上路
可可豆: 31 CB
威望: 33 点
在线时间: 139(时)
发自: Web Page
话说。。这不是socket的节奏么。
级别: 圣骑士
UID: 145603
可可豆: 584 CB
威望: 1052 点
在线时间: 385(时)
发自: Web Page
socket。。。
级别: 新手上路
可可豆: 185 CB
威望: 175 点
在线时间: 101(时)
发自: Web Page
node.js socket.io 模块。我上个项目搞的
Java Eye: @witcheryneRuby China: @lvjian700github: @lvjian700
级别: 侠客
UID: 85157
可可豆: 233 CB
威望: 406 点
在线时间: 293(时)
发自: Web Page
有现成的异步socket框架&&设置时间间隔发心跳包就可以啦
晚睡早起,多写少撸,锲而不舍,必成大器。
Pages: 1/2
关注本帖(如果有新回复会站内信通知您)
9*6-8 正确答案:46
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版查看: 21831|回复: 32
Android微信支付彻底扫坑
签到天数: 21 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
没有eoe的账号,级别还太低,出门如何吹牛逼?
才可以下载或查看,没有帐号?
由于公司运营需要,Android客户端要增加微信支付。在看了几遍官方文档之后,加上之前有集成微信分享的经验,所以很快就把调用微信支付的代码写好了,待微信支付相关接口完成后联调时,才发现山高路远坑深啊!从下午2点半开始调试,一直折腾到快6点,那个微信支付界面才“千呼万唤始出来”,更坑爹的是,压根儿就不是我客户端的问题,而是后台接口那边sign生成时出了问题。在解决问题的过程中,看到网上太多关于微信支付各种问题的帖子,但遗憾的是并没有找到真正有效的解决方案,所以就来彻底扫一下Android集成微信支付中的坑。首先讲一下我们的逻辑,如微信支付开发文档(https://pay./wiki/doc/api/app.php?chapter=8_5)中Android部分描述的那样,由服务器端请求微信支付平台生成prepayid,大家一般也都是这么做的,发现网上有一部分人从服务器端拿到prepayid后,在客户端自己拼字符串参数,然后调用算法生成sign,这样是可以,但是安全性不好,而且客户端逻辑也变复杂了,估计大家是按照官方demo写的,至于其demo暂时就不评价了,下面会提及。我们的做法是所有的必要参数,如partnerId、prapayId、packageValue、nonceStr、timeStamp、sign等都是由服务器端生成,至于appId自己写在客户端也行,服务器端传过来也行,因为之前微信分享appId是写在客户端了,因此微信支付就没让服务器端返回appId这个参数。其实微信支付官方文档也是这样建议的,原文为“商户服务器生成支付订单,先调用统一下单API(详见第7节)生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付”。App端拿到上述6个主要参数后,加上appId,一共7个,就可以调起支付了。如上所述,客户端的逻辑就这么简单,所以当调试时竟然调不出支付界面,真觉得不可思议。我遇到的问题是这样的:当发起支付时调不出微信支付界面,直接响应WXPayEntryActivity中的onResp回调,并且errCode始终返回-1。如果微信未登录,则会调起登陆界面,登陆完成后还是调不起来,errCode依然返回-1。我们客户端的实现逻辑基本跟官方文档一致(注意官方文档有个书写错误,在调用支付部分代码最后一行的参数中,request写成了req,后面也会提到),主要核心代码如下:1.首先注册,其中api为IWXAPI的实例
[java] view plaincopy
api = WXAPIFactory.createWXAPI(context, APP_ID, false);&&api.registerApp(APP_ID);&&
2.从服务端拿到上述必要参数后,调支付即可,其中params是自定义的用来保存从服务端获取的所有的对象
[java] view plaincopy
if (api != null) {&&& & if (isWXAppInstalled()) {&&& && &&&PayReq req = new PayReq();&&& && &&&req.appId = APP_ID;&&& && &&&req.partnerId = params.getPartnerId();&&& && &&&req.prepayId = params.getPrepayId();&&& && &&&req.packageValue = params.getPackageValue();&&& && &&&req.nonceStr = params.getNonceStr();&&& && &&&req.timeStamp = params.getTimeStamp();&&& && &&&req.sign = params.getSign();&&&&& && &&&api.sendReq(req);&&& & }&&}&&
3.WXPayEntryActivity这个回调界面实际上不会影响前面的调起支付的逻辑,写过微信分享的应该知道,这个Activity一定要放到“App包名.wxapi”的package中,否则无法响应回调,当然别忘了在AndroidManifest.xml中注册。微信分享的回调WXEntryActivity也是这样的,放在同一个包即可。没错,微信就是这么霸道。
Android客户端的核心逻辑就是这些,下面来一一列举微信支付中的坑,或者叫注意点吧,有些是我知道因此没有亲自踩上去的也一并列出。1.首先如果要使用微信支付的话,必须先到微信开放平台注册应用,具体地址为https://open./,注册时需要填应用的包名和签名,注意这里的签名是App正式版的签名,可以找一个已上线的包或打一个正式包,使用微信提供的工具(签名工具下载地址为https://open./zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)来获取,获取后填上即可。待审核通过后,会得到一个AppID和AppSecret,AppID分享和支付都要用到,AppSecret没什么实际用途,此时微信分享能力是直接拥有的,支付能力还要额外申请,其中涉及到财务信息等,最好让公司财务部门去申请,申请成功后会拿到一个商户id,后面生成sign时会用到。只有所有审核都通过后,才可调用微信支付功能,这点是前提。2.微信分享和微信支付SDK是同一个架包,名为libammsdk.jar。3.官方开发文档中有一处错误,需要注意下,如下图最后一行参数req应该为request,照搬代码的估计IDE也不会放过你,哈哈。
4.测试微信支付时,务必对自己的App做正式签名,因为一开始就在微信平台注册过签名信息,微信SDK会做校验,只有这样才能调起微信分享和微信支付,直接debug版的包则绝对调不起来,这点务必注意,很多人是跌在这里了!当初做微信分享曾遇到过,所以会很留心,也因为如此,如果微信分享能调起来,微信支付不行,那就不要怀疑签名问题了。5.还是签名,网上有人说要注意大小写,这点其实是不必的。在微信开放平台看到审核通过的App的签名是大写的,而用微信签名获取工具获得的则显示小写,这个没关系,不要贸然改动平台注册信息,不然又可能导致漫长的审核等待,上面也说了,微信分享如可以,那就不是签名问题。6.来说下官方demo,这东西害人不浅啊!很多人参考其写法,如生成sign放在客户端啊,调支付的Activity添加intent-filter啊,最主要的还是签名问题。其实客户端逻辑很简单,直接上手集成即可,demo看看逻辑就行,照抄小心掉坑里。7.网上有人说需要给调用支付的Activity配置如下intent-filter(见下图),可能也是被demo误导了
[html] view plaincopy
&intent-filter&&&& & &action android:name=&android.intent.action.VIEW&/&&&& & &category android:name=&android.intent.category.DEFAULT&/&&&& & &data android:scheme=&appid&/&&&&/intent-filter&&&
逻辑上来看,根本不会跳这个界面啊,所以当然是非必需的。8.对于errCode返回-1,有人说清除微信缓存或切换账户就好了,这种解决方案治标不治本啊,根本不能算解决方案。虽然我没遇到能用这方法解决的问题,但目测是签名的问题,建议还得找到真正的问题所在。9.生成sign时特别需要注意,首先将key-value键值对拼成字符串,注意key都要小写,如appid,noncestr,package,partnerid,prepayid,timestamp,key,并且名字得按上述名称,我们遇到的错误就是因为partnerid写成了partnerId,prepayid写成了PrepayId,当然我们是在服务端写的,如果在客户端生成sign的话,也需要注意大小写及名称,详细信息请参考官方文档。还有这里的key并非AppID或AppSectet,而是在商户平台设置的,官方描述为“key设置路径:微信商户平台(pay.)--&账户设置--&API安全--&密钥设置”。对于noncestr,申请prepayid和生成sign时两次需要用到,由于iOS同事看到相关文章说noncestr前后需要一致,因此这个随机字符串我们是设置成一样的了,这样做Android平台也是OK的,不过个人感觉这里可以不一致,由于这个逻辑在服务器端,我并没有验证,方便的同学可以验证下。10.req.packageValue=”Sign=WXPay”,一般都是这样写死这个参数值。也有人说写成req.packageValue=”prepay_id=” + prepayid,经测试Android两种写法都是可以调起微信支付的,至少最新版本SDK是可以的,以后则不清楚,官方也建议写Sign=WXPay,据说iOS只支持这种写法。11.对于IWXAPI实例的创建,官方代码为: IWXAPI api = WXAPIFactory.createWXAPI(context, null);这样写就可以,如果调用另一个工厂方法:IWXAPI api = WXAPIFactory.createWXAPI(context, APP_ID, false);也是OK的,我都测试过,总之这里不是问题的根源。不得不再次吐槽一下Android微信支付,支付宝之类的支付集成是很简单的,微信支付却花了几个小时才搞定,上面罗列了一系列注意事项,都是前人踩过的坑,希望大家看到这篇文章后,可以用20分钟搞定微信支付,如果还有问题,欢迎回复探讨。
原文可以参考个人CSDN博客:http://blog.csdn.net/ahence/article/details/
上海酒店***,足不出户就能体验高品味享受,我们全天候准备为您服务!使您全身活力再现!把轻松`舒适`和快乐带给您!官网电话/微信1:微信2:shanmo12580,务必同时加,qq:806 &
本帖被以下淘专辑推荐:
& |主题: 11, 订阅: 2
签到天数: 21 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
楼主,查询订单,你们用的是你们的订单号,还是微信的订单号,客户端需要轮询什么的吗 ...
这个是服务端做的,具体不太清楚。不过订单应该是在自己服务器的,微信订单只不过是中间一个支付凭证,应该还是用自己服务器为每一笔交易生成的订单号
签到天数: 23 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
我的微信支付我遇到一个奇葩问题。调起微信支付没问题也可以支付成功,但是,我调起温馨支付进入支付页面,然后我一步步退出APP以后,然后再打开微信客户端后那个支付的页面又重新调起来了,然后再后退,又退到应用里面去了,请问这是怎么回事啊。。。。
我也遇到这个问题了。
请问这个问题解决了吗?是怎么解决的?&
签到天数: 1 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
我的问题是第一次支付调起没有问题,但是之后就无法调起支付界面,直接返回-1,清理微信缓存之后可以成功调起一次但是之后还是返回-1,我想问一下如果签名文件有错误是不是应该一次也不能调起成功
签到天数: 35 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 66 天连续签到: 1 天[LV.6]常住居民II主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 7 天连续签到: 1 天[LV.3]偶尔看看II主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 74 天连续签到: 1 天[LV.6]常住居民II主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 2 天连续签到: 1 天[LV.1]初来乍到主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 30 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
微信支付到处是坑儿。。。
签到天数: 23 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
先mark一下,以后开发微信支付的时候看下,感谢楼主的分享!
签到天数: 41 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
mark一下,收藏着用
签到天数: 32 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
收藏一下,为以后要用到这一块时做下准备
签到天数: 117 天连续签到: 2 天[LV.6]常住居民II主题帖子e币
真心学习了。只是有个实例就更好了。自己笨慢慢学了。
签到天数: 21 天连续签到: 1 天[LV.4]偶尔看看III主题帖子e币
说白了微信就是娱乐的 干不了银行该干的活
签到天数: 59 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
谢谢分享谢谢分享
签到天数: 180 天连续签到: 1 天[LV.7]常住居民III主题帖子e币
不错不错&…………
签到天数: 173 天连续签到: 1 天[LV.7]常住居民III主题帖子e币
感谢楼主& &
挂在这了& &&&“因为partnerid写成了partnerId,prepayid写成了PrepayId,”
推荐阅读热门话题
620001874417415378324276275259255250225216210715
半小时前半小时前1&小时前4&小时前昨天&23:58昨天&19:08昨天&16:31昨天&14:30昨天&14:01昨天&13:20昨天&11:54前天&23:36前天&17:38前天&10:013&天前3&天前
Powered by
扫一扫 关注eoe官方微信转自:/hoojo/p/longPolling_comet_jquery_iframe_ajax.html
基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性。
一、什么是长连接、长轮询?
用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息。这里的&不停&其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已。
二、长连接、长轮询的应用场景
长连接、长轮询一般应用与WebIM、ChatRoom和一些需要及时交互的网站应用中。其真实案例有:WebQQ、Hi网页版、Facebook IM等。
如果你对服务器端的反向Ajax感兴趣,可以参考这篇文章 DWR 反向Ajax 服务器端推的方式:
欢迎大家继续支持和关注我的博客:
也欢迎大家和我交流、探讨IT方面的知识。
三、优缺点
轮询:客户端定时向服务器发送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)方式。如下图所示,它通常包含以下几个关键过程:
1. 轮询的建立& 建立轮询的过程很简单,浏览器发起请求后进入循环等待状态,此时由于服务器还未做出应答,所以HTTP也一直处于连接状态中。& 2. 数据的推送& 在循环过程中,服务器程序对数据变动进行监控,如发现更新,将该信息输出给浏览器,随即断开连接,完成应答过程,实现&服务器推&。& 3. 轮询的终止& 轮询可能在以下3种情况时终止:& & 3.1. 有新数据推送& && 当循环过程中服务器向浏览器推送信息后,应该主动结束程序运行从而让连接断开,这样浏览器才能及时收到数据。& & 3.2. 没有新数据推送& && 循环不能一直持续下去,应该设定一个最长时限,避免WEB服务器超时(Timeout),若一直没有新信息,服务器应主动向浏览器发送本次轮询无新信息的正常响应,并断开连接,这也被称为&心跳&信息。& & 3.3. 网络故障或异常& && 由于网络故障等因素造成的请求超时或出错也可能导致轮询的意外中断,此时浏览器将收到错误信息。& 4. 轮询的重建& 浏览器收到回复并进行相应处理后,应马上重新发起请求,开始一个新的轮询周期。
五、程序设计
1、普通轮询 Ajax方式
客户端代码片段
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&meta http-equiv="pragma" content="no-cache"&
&meta http-equiv="cache-control" content="no-cache"&
&meta http-equiv="author" content="hoojo & "&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&%@ include file="/tags/jquery-lib.jsp"%&
&script type="text/javascript"&
$(function () {
window.setInterval(function () {
$.get("${pageContext.request.contextPath}/communication/user/ajax.mvc",
{"timed": new Date().getTime()},
function (data) {
$("#logs").append("[data: " + data + " ]&br/&");
&div id="logs"&&/div&
客户端实现的就是用一种普通轮询的结果,比较简单。利用setInterval不间断的刷新来获取服务器的资源,这种方式的优点就是简单、及时。缺点是链接多数是无效重复的;响应的结果没有顺序(因为是异步请求,当发送的请求没有返回结果的时候,后面的请求又被发送。而此时如果后面的请求比前面的请求要先返回结果,那么当前面的请求返回结果数据时已经是过时无效的数据了);请求多,难于维护、浪费服务器和网络资源。
服务器端代码
@RequestMapping("/ajax")
public void ajax(long timed, HttpServletResponse response) throws Exception {
PrintWriter writer = response.getWriter();
Random rand = new Random();
// 死循环 查询有无数据变化
while (true) {
Thread.sleep(300); // 休眠300毫秒,模拟处理业务等
int i = rand.nextInt(100); // 产生一个0-100之间的随机数
if (i & 20 && i & 56) { // 如果随机数在20-56之间就视为有效数据,模拟数据发生变化
long responseTime = System.currentTimeMillis();
// 返回数据信息,请求时间、返回数据时间、耗时
writer.print("result: " + i + ", response time: " + responseTime + ", request time: " + timed + ", use time: " + (responseTime - timed));
// 跳出循环,返回数据
} else { // 模拟没有数据变化,将休眠 hold住连接
Thread.sleep(1300);
服务器端实现,这里就模拟下程序监控数据的变化。上面代码属于SpringMVC 中controller中的一个方法,相当于Servlet中的一个doPost/doGet方法。如果没有程序环境适应servlet即可,将方法体中的代码copy到servlet的doGet/doPost中即可。
服务器端在进行长连接的程序设计时,要注意以下几点:& 1. 服务器程序对轮询的可控性& 由于轮询是用死循环的方式实现的,所以在算法上要保证程序对何时退出循环有完全的控制能力,避免进入死循环而耗尽服务器资源。& 2. 合理选择&心跳&频率& 从图1可以看出,长连接必须由客户端不停地进行请求来维持,所以在客户端和服务器间保持正常的&心跳&至为关键,参数POLLING_LIFE应小于WEB服务器的超时时间,一般建议在10~20秒左右。& 3. 网络因素的影响& 在实际应用时,从服务器做出应答,到下一次循环的建立,是有时间延迟的,延迟时间的长短受网络传输等多种因素影响,在这段时间内,长连接处于暂时断开的空档,如果恰好有数据在这段时间内发生变动,服务器是无法立即进行推送的,所以,在算法设计上要注意解决由于延迟可能造成的数据丢失问题。& 4. 服务器的性能& 在长连接应用中,服务器与每个客户端实例都保持一个持久的连接,这将消耗大量服务器资源,特别是在一些大型应用系统中更是如此,大量并发的长连接有可能导致新的请求被阻塞甚至系统崩溃,所以,在进行程序设计时应特别注意算法的优化和改进,必要时还需要考虑服务器的负载均衡和集群技术。
上图是返回的结果,可以看到先发出请求,不一定会最先返回结果。这样就不能保证顺序,造成脏数据或无用的连接请求。可见对服务器或网络的资源浪费。
2、普通轮询 iframe方式
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&meta http-equiv="pragma" content="no-cache"&
&meta http-equiv="cache-control" content="no-cache"&
&meta http-equiv="expires" content="0"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&%@ include file="/tags/jquery-lib.jsp"%&
&script type="text/javascript"&
$(function () {
window.setInterval(function () {
$("#logs").append("[data: " + $($("#frame").get(0).contentDocument).find("body").text() + " ]&br/&");
$("#frame").attr("src", "${pageContext.request.contextPath}/communication/user/ajax.mvc?timed=" + new Date().getTime());
// 延迟1秒再重新请求
window.setTimeout(function () {
window.frames["polling"].location.reload();
&iframe id="frame" name="polling" style="display:"&&/iframe&
&div id="logs"&&/div&
这里的客户端程序是利用隐藏的iframe向服务器端不停的拉取数据,将iframe获取后的数据填充到页面中即可。同ajax实现的基本原理一样,唯一不同的是当一个请求没有响应返回数据的情况下,下一个请求也将开始,这时候前面的请求将被停止。如果要使程序和上面的ajax请求一样也可以办到,那就是给每个请求分配一个独立的iframe即可。下面是返回的结果:
其中红色是没有成功返回请求就被停止(后面请求开始)掉的请求,黑色是成功返回数据的请求。
3、长连接iframe方式
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&meta http-equiv="pragma" content="no-cache"&
&meta http-equiv="cache-control" content="no-cache"&
&meta http-equiv="author" content="hoojo & "&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&%@ include file="/tags/jquery-lib.jsp"%&
&script type="text/javascript"&
$(function () {
window.setInterval(function () {
var url = "${pageContext.request.contextPath}/communication/user/ajax.mvc?timed=" + new Date().getTime();
var $iframe = $('&iframe id="frame" name="polling"
src="' + url + '"&&/iframe&');
$("body").append($iframe);
$iframe.load(function () {
$("#logs").append("[data: " + $($iframe.get(0).contentDocument).find("body").text() + " ]&br/&");
$iframe.remove();
&div id="logs"&&/div&
这个轮询方式就是把刚才上面的稍微改下,每个请求都有自己独立的一个iframe,当这个iframe得到响应的数据后就把数据push到当前页面上。使用此方法已经类似于ajax的异步交互了,这种方法也是不能保证顺序的、比较耗费资源、而且总是有一个加载的条在地址栏或状态栏附件(当然要解决可以利用htmlfile,Google的攻城师们已经做到了,网上也有封装好的lib库),但客户端实现起来比较简单。
如果要保证有序,可以不使用setInterval,将创建iframe的方法放在load事件中即可,即使用递归方式。调整后的代码片段如下:
&script type="text/javascript"&
$(function () {
(function iframePolling() {
var url = "${pageContext.request.contextPath}/communication/user/ajax.mvc?timed=" + new Date().getTime();
var $iframe = $('&iframe id="frame" name="polling"
src="' + url + '"&&/iframe&');
$("body").append($iframe);
$iframe.load(function () {
$("#logs").append("[data: " + $($iframe.get(0).contentDocument).find("body").text() + " ]&br/&");
$iframe.remove();
iframePolling();
这种方式虽然保证了请求的顺序,但是它不会处理请求延时的错误或是说很长时间没有返回结果的请求,它会一直等到返回请求后才能创建下一个iframe请求,总会和服务器保持一个连接。和以上轮询比较,缺点就是消息不及时,但保证了请求的顺序。
4、ajax实现长连接
&%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false" %&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&meta http-equiv="pragma" content="no-cache"&
&meta http-equiv="cache-control" content="no-cache"&
&meta http-equiv="expires" content="0"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&%@ include file="/tags/jquery-lib.jsp"%&
&script type="text/javascript"&
$(function () {
(function longPolling() {
url: "${pageContext.request.contextPath}/communication/user/ajax.mvc",
data: {"timed": new Date().getTime()},
dataType: "text",
timeout: 5000,
error: function (XMLHttpRequest, textStatus, errorThrown) {
$("#state").append("[state: " + textStatus + ", error: " + errorThrown + " ]&br/&");
if (textStatus == "timeout") { // 请求超时
longPolling(); // 递归调用
// 其他错误,如网络错误等
longPolling();
success: function (data, textStatus) {
$("#state").append("[state: " + textStatus + ", data: { " + data + "} ]&br/&");
if (textStatus == "success") { // 请求成功
longPolling();
上面这段代码就是才有Ajax的方式完成长连接,主要优点就是和服务器始终保持一个连接。如果当前连接请求成功后,将更新数据并且继续创建一个新的连接和服务器保持联系。如果连接超时或发生异常,这个时候程序也会创建一个新连接继续请求。这样就大大节省了服务器和网络资源,提高了程序的性能,从而也保证了程序的顺序。
现代的浏览器都支持跨域资源共享(Cross-Origin Resource Share,CORS)规范,该规范允许XHR执行跨域请求,因此基于脚本的和基于iframe的技术已成为了一种过时的需要。
把Comet做为反向Ajax的实现和使用的最好方式是通过XMLHttpRequest对象,该做法提供了一个真正的连接句柄和错误处理。当然你选择经由HTTP长轮询使用XMLHttpRequest对象(在服务器端挂起的一个简单的Ajax请求)的Comet模式,所有支持Ajax的浏览器也都支持该种做法。
基于HTTP的长连接技术,是目前在纯浏览器环境下进行即时交互类应用开发的理想选择,随着浏览器的快速发展,html5将为其提供更好的支持和更广泛的应用。在html5中有一个websocket 可以很友好的完成长连接这一技术,网上也有相关方面的资料,这里也就不再做过多介绍。
阅读(...) 评论()

我要回帖

更多关于 android 轮询 的文章

 

随机推荐