本文地址: http://www.cnblogs.com/blackmanba/p/solve-socketIO-IE8-emit-disconnect-too-long.html或者http://forkme.info/solve-socketIO-IE8-emit-disconnect-too-long/, 转载请注明源地址。

概述

Node.js是一个是一个构建在Chrome's JavaScript runtime上的应用程序。能够容易的建立起快速, 可扩展性的应用。Node.js采用事件驱动, 无阻塞I/O模型来保证其轻量性和有效性。对于Javascript语言来说, Node.js的出现具有相当重要的意义。它意味着Javascript不再是传统意义上只能用于前端开发的语言, Javascript同时也能用于WEB后端程序的开发。Node.js相当于一座桥梁, 通过它可以打通前端与后端开发, 现在通过使用Javascript就能实现功能完备的网站。

在使用Node.js开发聊天模块的过程中, 采用Socket.IO实现聊天功能。Socket.IO是一个开源的库, 根据浏览器的兼容性不同采用不同的实现方式, 分别支持WebSocket, Adobe Flash Socket, AJAX long polling, AJAX multipart streaming, Forever Iframe以及JSONP Polling这些API。Socket.IO能兼容大部分的浏览器, 这也是它的最大优势。在使用Socket.IO实现聊天模块的过程中发现一个问题: 在IE8浏览器下聊天窗口关闭一分钟时才触发服务端的disconnect事件。这让聊天应用的实时性大打折扣。

原因

为什么IE8下会出现这个问题呢? 通过查询官方文档和日志输出, 发现是以下原因导致: IE8及以下浏览器不支持WebSocket协议, 在IE8浏览器中, Socket.IO是通过xhr-polling来实现数据传输的。服务器一分钟才会向客服端发送请求来确认client端是否断开连接。如此一来就会导致触发服务器disconnect事件的时间过长, 导致实时应用较晚响应, 影响用户体验。

解决方法

关于这个问题有以下三种不同的方法解决:

1. 使用flashsocket实现

这是最简单的一种实现方式, 通过使用flashsocket可以在用户关闭窗口时触发disconnect事件通知服务器进行相应的处理。以下是在Socket.IO服务器端的具体配置:

io.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);

使用这种方式的优点是实现简单。缺点如下:

  • 苹果系统不支持Flash
  • swf文件下载会有一定时间的延时。经过测试在IE8下加载时间大概是10s, 这会严重影响体验。

2. 配置Socket.IO通知时间

根据官方配置, Socket.IO默认是60s发送请求确认客服端是否断开连接。这是导致触发disconnect事件过慢的原因,可以将相关的时间缩短, 让服务端更快的发送请求。配置代码如下:

io.configure('production', function() {
io.set('heartbeat timeout', 2);
io.set('heartbeat interval', 1);
io.set('close timeout', 5);
io.set('polling duration', 3);
}); io.configure('development', function() {
io.set('heartbeat timeout', 2);
io.set('heartbeat interval', 1);
io.set('close timeout', 5);
io.set('polling duration', 3);
});

以上分别是生产环境和开发环境的配置, 各个参数的意义详见官方配置。通过配置, IE8触发disconnect的时间变为5s, 在一定程度上增强了实时性, 缺点如下:

  • 只是接近实时, 实际上还是要经过几秒的时间才会触发事件
  • 服务端发送确认请求的次数增加, 会占用更多的带宽以及更多消耗服务器的性能

3. 调用disconnect方法主动通知服务端

以WEB在线聊天为例。通过监听浏览器的onBeforeunload事件, 在窗口关闭前发送请求通知服务器并调用disconnect()方法主动关闭连接。实现代码如下:

// 使用jquery库监听浏览器的onBeforeunload事件
$(window).bind('beforeunload', function (e) { // 通知浏览器关闭连接
socket.disconnect(); /**
* 如果用户选择不关闭浏览器, 就要进行Socket的重新连接
* 第一个setTimeout的作用是将第二个setTimeout放置于执行队列中, 接下来执行return
* 阻塞了第二个setTimeout执行。确认关闭窗口时, 浏览器关闭不会执行第二个setTimeout,
* 取消关闭, 第二个setTimeout将会在1s后执行
**/
setTimeout(function () {
setTimeout(function () {
socket.socket.reconnect();
}, 1000);
}, 1); // 返回字符串, 让用户确认是否关闭页面
return "是否关闭窗口";
}

这种方式的最大好处就是在IE8下可以做到"实时"通知服务端关闭连接, 只取决于网络的快慢。当然缺点是实现有些复杂。

总结

新的协议如websocket的使用让开发变得更加简单。但在旧的浏览器上并没有这些新的协议。使用Socket.IO, 通过其内部的自动切换, 可以用同一套API兼容不同的浏览器。但不同底层实现方式的差别仍然存在。让低版本的浏览器兼容是我们在开发过程中必须考虑的问题。

解决Socket.IO在IE8下触发disconnect时间过长的更多相关文章

  1. IE8 下 select option 内容过长 , 展开时信息显示不全解决办法

    IE8 下 select option 内容过长 , 展开时信息显示不全 , 简单折衷的方式就是给 option 加上 title 属性 , 但是又不想一个个的修改,怎么办呢,代码如下 : //sel ...

  2. socket.io对IE8的支持

    默认下载了最新版的socket.io,版本号是1.7.2,对IE8的支持不好,反正在IE8下收发消息都不行.在网上查了很多资料,都解决不了IE8的问题,崩溃. 最后用了一个大家比较认可的版本1.0.6 ...

  3. 解决$.ajax请求在ie8下失效问题

    ie8下默认把跨域请求拦截了,需要用jquery.xdomainrequest.min.js 处理跨域问题,需放在jq下引入 http://cdnjs.cloudflare.com/ajax/libs ...

  4. 解决 document.getElementsByClassName 在 IE8 下的兼容下的问题

    H5中新增了一个令人期待已久的方法:getElementsByClassName,这个方法让我们可以通过 class 属性中的类名来访问元素,这是极好的. but! 这个方法在IE9以下的浏览器是不支 ...

  5. IE8下javascript的时间函数Date()不兼容问题,显示NAN【转】

    function parseISO8601(dateStringInRange) {   var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,       dat ...

  6. Socket.io:有点意思

    个人网站 欢迎品尝 edwardesire.com 下面页面就是使用Socket.io制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看).左边是游戏画面,右边是按键表和聊天室.画面达到红蓝版 ...

  7. socket.io简单说明及在线抽奖demo

    socket.io简单说明及在线抽奖demo socket.io 简介 Socket.IO可以实现实时双向的基于事件的通信. 它适用于各种平台,浏览器或设备,也同样注重可靠性和速度. socket.i ...

  8. .net下使用socket.io随笔记录

    一.问题背景 目前公司在互联网产品上需要程序与前端部分要进行一个实时交互,在进行一定程度上的选型后,决定使用socket.io框架进行一个实践,算是公司的一个新的 尝试,也算是给自己增加增长见闻,由于 ...

  9. Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最新攻略

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_163 首先得明确一点,和Django一样,在2020年Flask 1.1.1以后的版本都不需要所谓的三方库支持,即Flask-Ce ...

随机推荐

  1. Ext.grid.plugin.RowExpander的简单用法

    有时候,我们在grid里渲染数据时,由于某些字段的内容太长,而grid又不会自动出现滚动条,于是溢出的内容后面就会出现省略号, 导致信息展示不完全.如果,这个信息不太重要,展示不完全也无关紧要.可是, ...

  2. dojo 九 effects dojo/_base/fx 和 dojo/fx

    官方教程:Dojo Effects这里讲学习一下dojo如何实现淡入.淡出.滑动等效果.实现这些特殊的效果有两个包 dojo/_base/fx 和 dojo/fx.dojo/_base/fx 中提供了 ...

  3. SSO之CAS单点登录详细搭建教程

    本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...

  4. hdu 1829-A Bug's LIfe(简单带权并查集)

    题意:Bug有两种性别,异性之间才交往, 让你根据数据判断是否存在同性恋,输入有 t 组数据,每组数据给出bug数量n, 和关系数m, 以下m行给出相交往的一对Bug编号 a, b.只需要判断有没有, ...

  5. mysql高可用方案比较

    详见:High Availability Database Tools http://www.acquia.com/blog/high-availability-database-tools

  6. PDO数据库

    <?php //定义数据源$dsn = "mysql:dbname=testa;host=localhost"; //造PDO对象$pdo = new PDO($dsn,&q ...

  7. Android项目真的要去做混淆(加密)处理

    以前做项目做是懒得混淆代码,因为要处理各种第三方的混淆东西,像友盟里面加了第三方库,又要特殊处理混淆操作,所以很麻烦,也懒得去做混淆操作,so 你懂的:但今天我用一个反编译工具,发现一个很可怕的事情 ...

  8. JAVA反射技术的使用

    前言 在开发html使用jquery提交post的时候,可以使用jquery遍历from元素里面的input元素实现参数组合,这样就不用手动打参数了,特别是在参数很多的时候,费神费时. 我开发Andr ...

  9. maven3实战之设置HTTP代理

    maven3实战之设置HTTP代理 ---------- 有时候你所在的公司基于安全因素考虑,要求你使用通过安全认证的代理访问因特网.这种情况下,就需要为Maven配置HTTP代理,才能让它正常访问外 ...

  10. Storm中tuple的可靠性

    一.简介 Storm 可以保证 spout 发出的每条消息都能被“完全处理” ,这也是直接区别于其他实时系统的地方,如 S4. 请注意,spout 发出的消息后续可能会触发产生成千上万条消息 ,可以形 ...