设为首页 收藏本站
查看: 869|回复: 0

[经验分享] 关于浏览器收不到tomcat comet数据的分析

[复制链接]

尚未签到

发表于 2015-8-10 07:16:27 | 显示全部楼层 |阅读模式
  最近有一个基于web的通讯项目。经研究comet是很适合的技术,可以满足新项目的要求,对比了tomcat、jetty和glassfish决定还是使用常见的tomcat来进行测试和生产部署。tomcat的comet并不复杂,先用tomcat网站上的例子进行测试。
  客户端接收代码:
  function callback() //回调函数,对服务端的响应处理,监视response状态
{
  if(req.readystate==4) //请求状态为4表示成功
  {
  if(req.status==200) //http状态200表示OK
  {
                     //所有状态成功,执行此函数,显示数据
}
  }
}
  结果。。。。。没成功!!!
  用IE或FF(firefox)连接发送信息,接收数据的的IE或FF并没有任何数据显示出来。于是用sinffer录了一下网络包,发现数据其实已经从tomcat推下来了,也就是浏览器已经接受到了数据。为什么浏览器没有显示呢?。。。
  先研究一下tomcat推下来数据吧,tomcat使用chunked编码方式来进行报文体的传输。chunked编码是HTTP/1.1 RFC里定义的一种编码方式,因此所有的HTTP/1.1应用都应当支持此方式。
    chunked编码的基本方法是将大块数据分解成多块小数据,每块都可以自指定长度,其具体格式如下(BNF文法):
    Chunked-Body   = *chunk            //0至多个chunk
                     last-chunk         //最后一个chunk
                     trailer            //尾部
                     CRLF               //结束标记符
  chunk          = chunk-size [ chunk-extension ] CRLF   
                        chunk-data CRLF
   chunk-size     = 1*HEX
   last-chunk     = 1*("0") [ chunk-extension ] CRLF
  chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
   chunk-ext-name = token
   chunk-ext-val  = token | quoted-string
   chunk-data     = chunk-size(OCTET)
   trailer        = *(entity-header CRLF)     
  也就是当用chunked的返回数据时,最后需要有一个长度为0的数据包表明数据结束。而恰恰是comet的stream工作机制导致tomcat没有发送最后一个结束包给浏览器,浏览器认为数据没有接收完一直在等待,直到接收到最后一个包或者socket断开连接。
  知道了原因开始想解决办法。
  首先想的是从服务器端解决。如果手动发一个chunked结束包不久可以了?后来发现发了结束包浏览器就会断开连接,要想服务器可以继续推数据只能重新建立连接,stream成long polling了。
  服务器不行就从客户端想办法,既然IE认为数据没有接受全所以不会出发readystate==4这个状态,那我们用状态3可不可以呢?也就是改代码为:
  function callback() //回调函数,对服务端的响应处理,监视response状态
{
  if(req.readystate==3) //请求状态为4表示成功
  {
  if(req.status==200) //http状态200表示OK
  {
                     //所有状态成功,执行此函数,显示数据
}
  }
}
  结果是firefox可以正常运行,IE还是不行提示“数据没有准备好“。看来FF和IE存在差别,经查资料FF是基于Gecko引擎的,IE 则是基于Trident的。基于Gecko引擎的浏览器都可以很好的处理这种情况。这种方法不能使用,毕竟IE占据了绝大部分的浏览器市场。而且opera、safari等其他浏览器对这个的支持也都不同。
  经过几天的研究又回到了很老的iframe解决办法上,通过iframe tomcat和IE能够正常的工作了(FF还是有问题,数据回来到现实有延迟。由于我们的客户端都是IE所以这点也可以接受了)。最后就剩下一个小问题,IE上的加载图标不停老在那里转。。。。。
  经过搜索使用天才google工程师的解决办法,成功解决大功告成!
  以下是google的代码:
  
  

  initialize: function() {
  
  var userAgent = navigator.userAgent.toLowerCase();
  
  //alert(userAgent)
  if (/msie/.test(userAgent) && !/opera/.test(userAgent)) {
  
  // For IE browsers
  comet.connection = new ActiveXObject("htmlfile");
  comet.connection.open();
  comet.connection.write("");
  comet.connection.write("document.domain = '"+document.domain+"'; ");
  comet.connection.write("");
  comet.connection.close();
  comet.iframediv = comet.connection.createElement("div");
  comet.connection.appendChild(comet.iframediv);
  comet.connection.parentWindow.comet = comet;
  comet.iframediv.innerHTML = "";
  }
  
  if( /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) ) {
  // For Firefox browser
  comet.connection = document.createElement('iframe');
  comet.connection.setAttribute('id','comet_iframe');
  with (comet.connection.style) {
  left       = top   = "-100px";
  height     = width = "1px";
  visibility = "hidden";
  display    = 'none';
  }
  comet.iframediv = document.createElement('iframe');
  comet.iframediv.setAttribute('src', './Demo');
  comet.connection.appendChild(comet.iframediv);
  document.body.appendChild(comet.connection);
  
  }
  if (/webkit/.test(userAgent) || /opera/.test(userAgent)) {
  
  // for other browsers
  comet.connection = document.createElement('iframe');
  comet.connection.setAttribute('id',     'comet_iframe');
  comet.connection.setAttribute('src',    './Demo');
  with (comet.connection.style) {
  position   = "absolute";
  left       = top   = "-100px";
  height     = width = "1px";
  visibility = "hidden";
  }
  document.body.appendChild(comet.connection);
  
  }
  },
  
  // this function will be called from backend.jsp
  printServerTime: function (time) {
  $('abc').innerHTML = time;
  },
  
  onUnload: function() {
  if (comet.connection) {
  comet.connection = false; // release the iframe to prevent problems with IE when reloading the page
  }
  }
  }
  Event.observe(window,'load',comet.initialize);
  Event.observe(window, 'unload', comet.onUnload);
  
  
  总结一下,只能说现在的浏览器差别很大,想用一套代码适应所有的浏览器几乎是不可能。所以我觉,
  一、为不同的浏览器定制不同的客户代码  
  二、是用long polling方式开发,可以达到代码基本一致
  有什么不对的欢迎讨论,有啥好的经验也欢迎交流:)
  
本文来自CSDN博客,转载请标明出处:http://blog.iyunv.com/wei97081116/archive/2009/03/30/4036453.aspx

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-96673-1-1.html 上篇帖子: tomcat的数据库连接池的配置 ZT 下篇帖子: IIS vs Tomcat 与JSP vs ASP.NET
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表