解决Socket.IO在IE8下触发disconnect时间过长
本文地址: 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时间过长的更多相关文章
- IE8 下 select option 内容过长 , 展开时信息显示不全解决办法
IE8 下 select option 内容过长 , 展开时信息显示不全 , 简单折衷的方式就是给 option 加上 title 属性 , 但是又不想一个个的修改,怎么办呢,代码如下 : //sel ...
- socket.io对IE8的支持
默认下载了最新版的socket.io,版本号是1.7.2,对IE8的支持不好,反正在IE8下收发消息都不行.在网上查了很多资料,都解决不了IE8的问题,崩溃. 最后用了一个大家比较认可的版本1.0.6 ...
- 解决$.ajax请求在ie8下失效问题
ie8下默认把跨域请求拦截了,需要用jquery.xdomainrequest.min.js 处理跨域问题,需放在jq下引入 http://cdnjs.cloudflare.com/ajax/libs ...
- 解决 document.getElementsByClassName 在 IE8 下的兼容下的问题
H5中新增了一个令人期待已久的方法:getElementsByClassName,这个方法让我们可以通过 class 属性中的类名来访问元素,这是极好的. but! 这个方法在IE9以下的浏览器是不支 ...
- IE8下javascript的时间函数Date()不兼容问题,显示NAN【转】
function parseISO8601(dateStringInRange) { var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/, dat ...
- Socket.io:有点意思
个人网站 欢迎品尝 edwardesire.com 下面页面就是使用Socket.io制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看).左边是游戏画面,右边是按键表和聊天室.画面达到红蓝版 ...
- socket.io简单说明及在线抽奖demo
socket.io简单说明及在线抽奖demo socket.io 简介 Socket.IO可以实现实时双向的基于事件的通信. 它适用于各种平台,浏览器或设备,也同样注重可靠性和速度. socket.i ...
- .net下使用socket.io随笔记录
一.问题背景 目前公司在互联网产品上需要程序与前端部分要进行一个实时交互,在进行一定程度上的选型后,决定使用socket.io框架进行一个实践,算是公司的一个新的 尝试,也算是给自己增加增长见闻,由于 ...
- Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最新攻略
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_163 首先得明确一点,和Django一样,在2020年Flask 1.1.1以后的版本都不需要所谓的三方库支持,即Flask-Ce ...
随机推荐
- Ext.grid.plugin.RowExpander的简单用法
有时候,我们在grid里渲染数据时,由于某些字段的内容太长,而grid又不会自动出现滚动条,于是溢出的内容后面就会出现省略号, 导致信息展示不完全.如果,这个信息不太重要,展示不完全也无关紧要.可是, ...
- dojo 九 effects dojo/_base/fx 和 dojo/fx
官方教程:Dojo Effects这里讲学习一下dojo如何实现淡入.淡出.滑动等效果.实现这些特殊的效果有两个包 dojo/_base/fx 和 dojo/fx.dojo/_base/fx 中提供了 ...
- SSO之CAS单点登录详细搭建教程
本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...
- hdu 1829-A Bug's LIfe(简单带权并查集)
题意:Bug有两种性别,异性之间才交往, 让你根据数据判断是否存在同性恋,输入有 t 组数据,每组数据给出bug数量n, 和关系数m, 以下m行给出相交往的一对Bug编号 a, b.只需要判断有没有, ...
- mysql高可用方案比较
详见:High Availability Database Tools http://www.acquia.com/blog/high-availability-database-tools
- PDO数据库
<?php //定义数据源$dsn = "mysql:dbname=testa;host=localhost"; //造PDO对象$pdo = new PDO($dsn,&q ...
- Android项目真的要去做混淆(加密)处理
以前做项目做是懒得混淆代码,因为要处理各种第三方的混淆东西,像友盟里面加了第三方库,又要特殊处理混淆操作,所以很麻烦,也懒得去做混淆操作,so 你懂的:但今天我用一个反编译工具,发现一个很可怕的事情 ...
- JAVA反射技术的使用
前言 在开发html使用jquery提交post的时候,可以使用jquery遍历from元素里面的input元素实现参数组合,这样就不用手动打参数了,特别是在参数很多的时候,费神费时. 我开发Andr ...
- maven3实战之设置HTTP代理
maven3实战之设置HTTP代理 ---------- 有时候你所在的公司基于安全因素考虑,要求你使用通过安全认证的代理访问因特网.这种情况下,就需要为Maven配置HTTP代理,才能让它正常访问外 ...
- Storm中tuple的可靠性
一.简介 Storm 可以保证 spout 发出的每条消息都能被“完全处理” ,这也是直接区别于其他实时系统的地方,如 S4. 请注意,spout 发出的消息后续可能会触发产生成千上万条消息 ,可以形 ...