Http协议中的Content-Length
追查得到的信息是,客户端是qq手机浏览器,通过gprs上网,网速很慢,有时候可能导致server认为tcp连接超时而切断连接. 假设一个文件2M,客户端收到了1.5M,之后停顿15秒,则server关闭连接,客户端就把这1.5M的文件当作完整文件交给上层应用,导致服务不可用.
实际上,我们的http回复是有Content-Length头部的,这个头部指明了文件长度是2M.根据http协议4.4节的规定,客户端必须告知用户接收到的文件长度和content-length不一致,但是qq手机浏览器没有这样做.这是违反http协议的.
之后用firefox和ie测试拉一个jpg文件, 故意把content-length写得比实际发送的数据大, 发现这些浏览器也没有遵守这条规定,都是默默的就把图片解析并展现出来了, 也许是出于避免太频繁的骚扰用户的考虑,毕竟网络失败是比较常见的.
但是我在http回复中把Content-Type设置为application/octet-stream,让firefox启动下载管理弹窗,在接收到的数据明显小于Content-Length的情况下, firefox还是默默的显示下载成功,这个就太不厚道了.
修改了web server, 异常切断改用rst包而不是fin包,浏览器就都报错了.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
4.4 Message Length
When a Content-Length is given in a message where a message-body is allowed, its field value MUST exactly match the number of OCTETs in the message-body. HTTP/1.1 user agents MUST notify the user when an invalid length is received and detected.