转载

HTTP请求中的Keep-Alive模式详解

介绍

最近遇到一个诡异问题,使用Fiddler替换某一个接口请求时,页面请求该接口后,请求一直没有结束的问题。经过定位,确定是HTTP中某些header字段导致的。本篇就是关于这几个字段的介绍。

Keep-Alive模式

我们都知道HTTP是基于TCP的,每一个HTTP请求都需要进行三步握手。如果一个页面对某一个域名有多个请求,就会进行频繁的建立连接和断开连接。所以HTTP 1.0中出现了 Connection: keep-alive ,用于建立长连接,即我们所说的Keep-Alive模式。下图是普通模式和长连接模式的请求对比:

HTTP请求中的Keep-Alive模式详解

HTTP/1.0中默认使用Connection: close。在HTTP/1.1中已经默认使用Connection: keep-alive。

通过对比可以看出,Keep-Alive模式更加高效,因为避免了连接建立和释放的开销。但是,如果一个连接是不会断开的,那么多个请求之间如何进行区分呢?也就是说浏览器是如何知道当前请求已经完成了呢?为了解决这个问题,HTTP对header中又添加了一个 Content-Length 字段。

Content-Length

Content-Length 表示实体内容的长度。浏览器通过这个字段来判断当前请求的数据是否已经全部接收。

所以,当浏览器请求的是一个静态资源时,即服务器能明确知道返回内容的长度时,可以设置 Content-Length 来控制请求的结束。但当服务器并不知道请求结果的长度时,如一个动态的页面或者数据, Content-Length 就无法解决上面的问题,这个时候就需要用到 Transfer-Encoding 字段。

Transfer-Encoding

Transfer-Encoding 是指传输编码,还有一个类似的字段叫做: Content-Encoding 。两者的区别是 Content-Encoding 用于对实体内容的压缩编码,比如 Content-Encoding: gzipTransfer-Encoding 则改变了报文的格式,比如上面的问题中,当服务端无法知道实体内容的长度时,就可以通过指定 Transfer-Encoding: chunked 来告知浏览器当前的编码是将数据分成一块一块传递的。当然, 还可以指定 Transfer-Encoding: gzip, chunked 表明实体内容不仅是gzip压缩的,还是分块传递的。最后,当浏览器接收到一个长度为0的chunked时, 知道当前请求内容已全部接收。

总结

好了,关于Keep-Alive模式的内容讲完了。回到最开始说的遇到的问题。当Fiddler替换的结果中,header指定的 Transfer-Encoding: chunked 或者 Connection: keep-alive 或者 Content-Length 的值和正文长度不符时,浏览器是不能正确解析替换后的结果的。解决方法是:将替换结果header中的 Transfer-Encoding , Content-Length 都删除,并且设置 Connection: close 来关闭请求的长连接模式,这样,Fiddler替换后的结果就是一个普通的连接请求结果,可以正常被浏览器解析。

原文  https://segmentfault.com/a/1190000008359278
正文到此结束
Loading...