解决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 ...
随机推荐
- (原创)3.2 AddOwner和OverrideMetadata的区别
1 AddOwner和OverrideMetadata 1.1 分析 从源代码上看,AddOwner函数中调用了OverrideMetadata, 并且把本类和依赖属性的哈希值加入到依赖属性的一张哈希 ...
- 无线路由器WDS设置方法图解_无线桥接设置
随着无线网络的发展,现在越来越多的公司及企业都已经开始布局无线局域网,今天我们主要介绍下适合中小企业的无线路由器桥接或WDS功能.文章以TP-link WR841N无线路由器设置为例,其它路由器参考设 ...
- android布局 及 布局属性
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> ...
- c 建立工程 常见错误及心得总结
1. 调用函数里面的 调用子函数,要是出现已定义错误,则要看看,是不是主函数的 头文件写成.c啦,因为在.h里面也定义可一次,要是写.c出现两次 错误提示:UrlCheck.obj : error L ...
- html5 移动端单页面布局
序 移动端的web网页使用的是响应式设计,但一般我们看到的网站页面都是跳转刷新得到的,比如通过点击一个menu后进入到另一个页面 今天来说下是移动端的单页面的布局.单页面就是一切操作和布局都是 ...
- [Android教程]EditText设置/隐藏光标位置、选中文本和获取/清除焦点
有时候需要让光标显示在EditText的指定位置或者选中某些文本.同样,为了方便用户输入以提升用户体验,可能需要使EditText获得或失去焦点. 1. 设置光标到指定位置 EditText et ...
- UVa 129 Krypton Factor【回溯】
学习的紫书的回溯,理解起来还是好困难的说啊= = #include<iostream> #include<cstdio> #include<cstring> #in ...
- [Linux] Git: 基本使用
Git 属于分布式版本控制系统( Distributed Version Control System,简称 DVCS )客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来.这么一 ...
- 菜鸟学习笔记2,$(document).ready()使用讨论
$(document).ready()使用讨论 $(document).ready() 一.先为说说 $(document).ready() 的功能: 1. JQuery API对 $(docume ...
- Service完全解析(转)
今天我们来讲一下Android中Service的相关内容. Service在Android中和Activity是属于同一级别上的组件,我们可以将他们认为是两个好哥们,Activity仪表不凡,迷倒万千 ...