由于http协议的简单性以及业务的需要,我们不可避免地需要自己去实现一些走http协议的server

当我们的短连接http服务器(如验证码服务器)是客户端是浏览器(iefirefoxchrome)的时候,有一个问题需要特别注意,我称之为短连接http服务器陷阱。首先,先来看下面一系列同一个请求,但是不同抓包工具抓取的内容的截图:

1.使用httpwatch抓包获取的内容

2.使用sniffer抓包获取的内容

其中,两者是同一个请求,从sniffer抓包内容看、浏览器和server已经完成了交互过程。但是浏览器(包括iefirefoxchrome)Result却是ERROR_INTERNET_CONNECTION_RESET,这是为什么呢?

通过走读server代码,发现server做了这样一个逻辑,在有请求过来的时候只读取了100个字节,因为server认为这100个字节足够判断客户端的请求行为(GET /HTTP/1.0 少于100个字节),而其它请求信息(包括cookie等等)是无用的,然后返回response信息,然后关闭连接。流程如下:

1)读取100个字节 => 2)返回response信息 => 3)关闭socket

当客户端请求的量不大的时候(内网开发机并发请求量<100)、很容易出现上文所述http服务器陷阱的问题。当客户端请求的量很大的时候,出现上述问题的几率倒不大,但是偶尔也会出现。分析原因如下:

当并发量很少的时候,server读取了100个字节并返回response后,马上关闭连接。由于并发量少,server处理速度很快,这样很快就会关闭了连接。但是,此时客户端(浏览器)也许还有一些数据(例如cookie信息等)并没有真正发送到server的内核缓冲区。于是,浏览器继续把剩余的数据试图发送到server,但是,此时发现server已经关闭了连接,就会引发ERROR_INTERNET_CONNECTION_RESET错误。虽然用sniffer抓包发现实际上整个交互过程已经完成,但是浏览器缺认为这是一个致命的错误,获取到的返回数据并没有正确的显示在浏览器上。

当并发量很大的时候,虽然server只读取了100个字节,但是由于服务器的处理能力有限,从读取了100字节到关闭连接的过程有一定的时间差。客户端可以在这个时间差的时间内把剩余的数据发送到了server内核缓冲区(虽然应用程序没有读取这部分数据)。因此,出现ERROR_INTERNET_CONNECTION_RESET错误的概率就会变小。

总结,在实现短连接的http服务器(尤其是提供给浏览器使用的服务器)时,尽量把http header数据包读取完整,不要因为只需要一小部分header信息就能处理请求而不读取其它的头部信息,以此来加快处理速度或者节省空间。这往往适得其反,可能会引起一些列不可预料的问题。

由此,引发另一个思考,既然不可避免的需要读取完整的http header数据包,那么,浏览器请求的时候,应该尽量保持http header不要过于庞大,既是为了减缓server的压力也是为了加快server的处理速度。而减少http header长度的最好方法就是减少cookie的内容。
来自: http://hi.baidu.com/yancncen/blog/item/2b79c4a2c8e83ba7cbefd091.html