本文地址: 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. (原创)3.2 AddOwner和OverrideMetadata的区别

    1 AddOwner和OverrideMetadata 1.1 分析 从源代码上看,AddOwner函数中调用了OverrideMetadata, 并且把本类和依赖属性的哈希值加入到依赖属性的一张哈希 ...

  2. 无线路由器WDS设置方法图解_无线桥接设置

    随着无线网络的发展,现在越来越多的公司及企业都已经开始布局无线局域网,今天我们主要介绍下适合中小企业的无线路由器桥接或WDS功能.文章以TP-link WR841N无线路由器设置为例,其它路由器参考设 ...

  3. android布局 及 布局属性

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> ...

  4. c 建立工程 常见错误及心得总结

    1. 调用函数里面的 调用子函数,要是出现已定义错误,则要看看,是不是主函数的 头文件写成.c啦,因为在.h里面也定义可一次,要是写.c出现两次 错误提示:UrlCheck.obj : error L ...

  5. html5 移动端单页面布局

    序     移动端的web网页使用的是响应式设计,但一般我们看到的网站页面都是跳转刷新得到的,比如通过点击一个menu后进入到另一个页面 今天来说下是移动端的单页面的布局.单页面就是一切操作和布局都是 ...

  6. [Android教程]EditText设置/隐藏光标位置、选中文本和获取/清除焦点

      有时候需要让光标显示在EditText的指定位置或者选中某些文本.同样,为了方便用户输入以提升用户体验,可能需要使EditText获得或失去焦点. 1. 设置光标到指定位置 EditText et ...

  7. UVa 129 Krypton Factor【回溯】

    学习的紫书的回溯,理解起来还是好困难的说啊= = #include<iostream> #include<cstdio> #include<cstring> #in ...

  8. [Linux] Git: 基本使用

    Git 属于分布式版本控制系统( Distributed Version Control System,简称 DVCS )客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来.这么一 ...

  9. 菜鸟学习笔记2,$(document).ready()使用讨论

    $(document).ready()使用讨论 $(document).ready()  一.先为说说 $(document).ready() 的功能: 1. JQuery API对 $(docume ...

  10. Service完全解析(转)

    今天我们来讲一下Android中Service的相关内容. Service在Android中和Activity是属于同一级别上的组件,我们可以将他们认为是两个好哥们,Activity仪表不凡,迷倒万千 ...