在做项目的时候,遇到一个很奇葩的问题,公司再监督影像查询模块,在点击看图按钮后,网页上展现图像和业务信息,然后把网页关闭,重复做这种动作两次或者更多次后,将会出现浏览器点击无响应的情况。这种情况在不同的浏览器下面,表现的还不尽相同。IE6浏览器重复2次,将不会响应,ie8重复十几次或者几次,也会出现不响应。IE9表现得更加稳定,几乎不会出现无响应的现象,偶尔出现。但有些客户使用的是IE6浏览器,这就比较让人烦躁了,看两张图像后,浏览器就会出现无响应的状况,这样子是会让人疯掉的。
该问题从发现到解决,大概经历了三个月时间。从开始怀疑前端页面代码有问题,到怀疑后台代码有问题,到最后怀疑是操作系统的问题,各种怀疑后,都未能找到根本原因。
最后,在出现问题的时候,我用 netstat-a 查看了本机与服务器的连接状态,发现其中本地与服务器的两个http连接都是处于close_wait状态,这是个不完全关闭的状态。tcp/ip
协议中,一个连接在创建时,要经过三次握手协议,在关闭时要经过四次握手协议。
对比那些运行正常的网页,可以发现,网页中使用的http连接是短连接,客户端在发送请求,接受服务器的请求后,该连接则会关闭。如果是出现close_wait状态后,说明连接未完全关闭,问题应该就是出现在这里了。
百度,google后,得知 IE6至多允许和每个服务2个连接,ie8至多允许6个连接,这就可以解释为什么ie6在点击两次后,就无响应,而ie8则要重复十几次或者几次才会出现无响应。 原因应该是:浏览器发现有两个未完全关闭的连接后,将不再创建新的连接,而是使用这两个未完全关闭的连接,由于是处于close_wait状态,浏览器是无法向服务器发送请求的。close_wait的原因是:浏览器主动向服务器发送关闭请求,但却没有接到服务器发送的关闭请求,此时,浏览器不能向服务器发送数据,而服务器是可以向浏览器发送数据的。这里解释了点击看图按钮无响应的原因。
从上面的分析来看,还是代码出现了问题。在反复观察代码和对比未出问题的其他功能的代码后,发现影像再监督功能在关闭事件onbeforeunload发生的时候,利用dwr,向服务器发送了一条解锁的请求,然后立刻关闭了窗口。问题就是出现在这里,是造成http连接未完全关闭的原因。因为tcp/ip协议在关闭时会经过四次握手,是需要时间的,如果还未等服务器发出关闭标识,自己立刻退出,浏览器将接收不到服务器的关闭请求,造成连接未完全关闭。
问题原因找到后, 相应的解决方法也有了。