我们知道Http协议是基于TCP/IP连接的,也就是说客户端浏览器向服务器发出一个Http请求并得到响应是要建立一条TCP/IP连接的,但是如果每发出一个Http请求客户端就要向服务器端建立一条TCP/IP连接的话,这样效率会非常低,所以在Http协议中有一个叫做Keep-Alive的机制,如果在服务器端(IIS或Apache等Web服务器)启动Keep-Alive后,客户端浏览器向Web服务器发出的Http请求被响应后建立的TCP/IP连接并不会被立刻释放掉,而是会存在一段时间,这个时间叫Keep-Alive Timeout,如果在Keep-Alive Timeout时间内没有新的Http请求从客户端发送到服务器端,那么建立的TCP/IP连接就会被服务器端释放掉,如果在Keep-Alive Timeout时间内又有Http请求从客户端浏览器发送到了服务器端,那么服务器端又会等待Keep-Alive Timeout时间后才会释放TCP/IP连接,这样大大提高了TCP/IP连接在Http协议中的复用率提高系统性能。这个过程可以用下面这张图来解释,左边是没有启用Keep-Alive时Http请求的状况,可以看到客户端每发出一次Http请求,都会和服务器端建立(open)一个TCP/IP连接然后释放(close)链接,右边是启用Keep-Alive后Http请求的状况,客户端发出的3个Http请求都复用同一个TCP/IP连接。

清楚了Keep-Alive是什么东西我们再来说说Keep-Alive中的另一个概念叫max,启用了Keep-Alive的Http连接,在Http响应头中一般会包含两个参数timeout和max,timeout就是我们在上面提到的Keep-Alive Timeout时间,在这个时间内如果没有新的Http请求发送到服务器端那么TCP/IP连接就会被服务器端释放掉,而max是表示TCP/IP连接还可以复用的次数,每当TCP/IP连接被Keep-Alive机制复用一次max的值就会减1,如果max等于0了,表示该TCP/IP连接不允许再被复用了,服务器端就会释放TCP/IP连接,如果客户端后面又有Http请求发送到服务器端,客户端和服务器端就必须重新建立一个TCP/IP连接。下图就是服务器端启用Keep-Alive机制后,客户端浏览器收到的Http响应头,里面包含timeout和max两个字段值。

从上面我们知道了如果服务器端启用了Keep-Alive机制,那么有两种情况建立的TCP/IP连接会被正常释放(非正常释放就不提了,比如关机了,断网了等。。。),一是在Keep-Alive Timeout时间内没有新的Http请求复用TCP/IP连接,那么TCP/IP连接就会被服务器端释放,二是当建立的TCP/IP连接被复用了max次后,max的值已经为0,服务器端也会释放TCP/IP连接。

当服务器端启用Keep-Alive机制后,会向客户端浏览器发送两个参数timeout和max,所以客户端浏览器就会知道Keep-Alive机制下建立的TCP/IP连接多久后会被服务器端释放掉,TCP/IP连接还能复用多少次,如果浏览器发现TCP/IP连接已经被服务器端释放掉了,那么浏览器就会和服务器端建立一个新的TCP/IP连接来发送后续的Http请求。但是有一种情况会导致IE浏览器不知道服务器端释放了TCP/IP连接,而去复用TCP/IP连接导致:“SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成” 错误发生。

我们来举个例子,还是下面这个截图,当IE浏览器收到这个Http响应标头之后就知道服务器端启用了Keep-Alive机制,并且Keep-Alive机制的timeout时间是5秒,最大复用次数为100次。

现在假如我们有个页面使用javascript的setInterval函数每过5秒钟就向服务器端发送一个Ajax请求,那么IE浏览器在向服务器端发送Ajax请求的时候就有可能会去复用服务器端已经被释放掉的TCP/IP连接。因为IE浏览器发送Ajax请求的时间间隔是5秒,而服务器端Keep-Alive机制timeout时间也是5秒,那么IE浏览器发出Ajax请求和服务器端释放TCP/IP连接这两个事情就很有可能在同一个时间点上发生。我们设想一下当IE浏览器发出第一次Ajax请求时和服务器端建立了一个TCP/IP连接,由于服务器端启用了Keep-Alive机制,该TCP/IP连接在5秒后才会被服务器端释放掉,而在5秒后IE浏览器开始发送第二次Ajax请求的时候认为5秒时间还没到还可以复用第一次Ajax请求建立的TCP/IP连接,所以当IE浏览器发出第二次Ajax请求的时候就沿用了第一次Ajax请求建立的TCP/IP连接,但是当第二次发出的Ajax请求到达服务器端的时候已经是第一次Ajax请求到达服务器端的时间的5秒后了(我们假定Ajax请求会在网络上传输1秒到达服务器端,那么当第二次Ajax请求到达服务器端的时候距离第一次Ajax请求已经有6秒的时间了),所以TCP/IP连接已经被服务器端释放掉了,那么IE浏览器发出的第二次Ajax请求就会被服务器端抛弃,服务器端不会对IE浏览器发出的第二次Ajax请求作出任何响应,所以IE浏览器就会抛出:“SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成” 错误。我们可以用下面一个时序图来描述这个过程:

经测试这个问题只会在IE(测试环境为IE11)浏览器上发生,在Firefox和Chrome上并无此问题,说明Firefox和Chrome在发出Http请求之前会去检测Keep-Alive机制建立的TCP/IP连接是否已经被释放掉了,如果释放掉了Firefox和Chrome不会报错而是向服务器端开启一个新的TCP/IP连接,避免复用已释放的TCP/IP连接这种情况发生,而IE浏览器就比较笨了,一旦复用了已释放的TCP/IP连接就报错了。。。

说了这么多那么怎样避免IE浏览器因为复用已释放的TCP/IP连接而报错呢?最保险的方法是关闭服务器端的Keep-Alive机制,尽管这样系统效率会有所下降但是这样IE浏览器肯定不会因为复用被释放的连接而报错了。。。另外也可以建议用户不要使用IE浏览器,这肯定是不现实的。。。。最后如果把Keep-Alive机制的timeout时间设置长一点而不是像本例一样只设置到5秒,也可以大大降低IE浏览器复用被释放连接的风险,但是不能够保证肯定是安全的。

下面介绍下怎样在IIS7中关闭Keep-Alive机制,另外设置Keep-Alive机制的timeout时间

IIS7关闭Keep-Alive机制,进入站点设置,然后选择HTTP Response Headers设置,点击Set Common Headers,将Enable HTTP keep-alive复选框取消选中即可。

IIS7设置Keep-Alive机制的timeout时间,在站点设置中点击高级设置(Advanced Settings),然后在弹出的窗口中设置Connection Time-out的值即可,默认是120秒即2分钟。

IE中Keep-Alive机制引起的错误的更多相关文章

  1. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  2. 别再为了this发愁了------JS中的this机制

    别再为了this发愁了------JS中的this机制 题记:JavaScript中有很多令人困惑的地方,或者叫做机制.但是,就是这些东西让JavaScript显得那么美好而与众不同.比方说函数也是对 ...

  3. SQL Server 内存中OLTP内部机制概述(二)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  4. MySQL数据库InnoDB存储引擎中的锁机制

    MySQL数据库InnoDB存储引擎中的锁机制    http://www.uml.org.cn/sjjm/201205302.asp   00 – 基本概念 当并发事务同时访问一个资源的时候,有可能 ...

  5. 利用linux信号机制调试段错误(Segment fault)

    在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...

  6. KTHREAD 线程调度 SDT TEB SEH shellcode中DLL模块机制动态

    KTHREAD 线程调度 SDT TEB SEH shellcode中DLL模块机制动态获取 <寒江独钓>内核学习笔记(5)   继续我们的线程相关的数据结构的学习.接下来我们学习 KTH ...

  7. ECshop中的session机制理解

    ECshop中的session机制理解     在网上找了发现都是来之一人之手,也没有用自己的话去解释,这里我就抛砖引玉,发表一下自己的意见,还希望能得到各界人士的指导批评! 此session机制不需 ...

  8. TensorFlow中的通信机制——Rendezvous(一)本地传输

    背景 [作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 在TensorFlow源码中我们经常能看到一个奇怪的词——Rendezvous ...

  9. React中如何优雅的捕捉事件错误

    React中如何优雅的捕捉事件错误 前话 人无完人,所以代码总会出错,出错并不可怕,关键是怎么处理. 我就想问问大家react的错误怎么捕捉呢? 这个时候: 小白:怎么处理? 小白+: ErrorBo ...

随机推荐

  1. CAD迷你看图

    CAD迷你看图http://www.aec188.com/CAD迷你看图 2016R12超快.超小的CAD多功能看图工具,完全脱离AutoCAD浏览R14-R2016各版本DWG/DXF/DWF的二三 ...

  2. 【bzoj1098】办公楼

    [bzoj1098]办公楼 题意 FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄 ...

  3. AOP设计思想_开发流程

    程序员一直在努力做一件事请,写更少的代码,做更多的事情,提高开发效率 在一个开发团队里面,一个人最多只做一件事情,绝对不会说,刚接手做了没多久的任务,上头又交给你另一项任务,绝对不会有的 下面,梦逸来 ...

  4. MyEclipse常用设置

    中文乱码设置:1.window-->preference-->general-->content type然后在<Content Types>中展开每一颗子项,并在< ...

  5. Java完成最简单的WebService创建及使用(REST方式,Jersey框架)

    前言: 一直以来都对WebService感兴趣,但因为难以理解WebService到底是什么,所以了解甚少.周二的时候有个跟我关系比较好的同事想要自己写个WebService的小Demo,希望能够做成 ...

  6. ABAP字符串翻转

    就这个函数STRING_REVERSE 略显蛋疼,好搞那么复杂.... 简单的转换嘛: FUNCTION ZSTRING_REVERSE. *"----------------------- ...

  7. linux 安装 ftp

    1 安装 vsftpd 查看是否已经安装 vsftpd rpm -qa | grep vsftpd 如果没有 则安装  安装命令如下 yum -y install vsftpd 设置开机启动 chkc ...

  8. 自定义控件之 TextBox

    //textbox typevar boxType = { WaterMarkBox: 0, ValidateBox: 1, SearchBox: 2}var textBoxObj = functio ...

  9. oracle 11g 一直提示 严重: 监听程序未启动或数据库服务未注册到该监听程序

    From:http://blog.sina.com.cn/s/blog_6734ea6d0102v6sn.html 增加操作系统环境变量:ORACLE_HOSTNAME=localhost 然后在cm ...

  10. Android通过HttpURLConnection链接到网络,并获取网络数据

    1.判断网络是否连接 private void networkIsconnected(String str){ ConnectivityManager connMgr = (ConnectivityM ...