分析下TCP包:
21~23:是TCP连接三次握手的过程;
24:服务端通知客户端窗口大小变更;
25:也就是第一个高亮的行,发起HTTP请求,尝试获取一串葡萄;
27~41:服务端分块多次推送了一颗颗的葡萄给到客户端;
43:最终在HTTP应用层,拿到了完整的一串葡萄,10个Data chunk对应10颗葡萄:
页面展示如下:
grape 1 grape 2 grape 3 grape 4 grape 5 grape 6 grape 7 grape 8 grape 9 grape 10根据以上抓包的报文格式,可以得到最终的HTTP响应报文格式如下:
注意:
分块传输和编码只在HTTP/1.1版本中提供。
HTTP/2不支持分块传输,因为其本身提供的更加高级的流传输实现了类似的功能。
4.2.2、范围请求范围请求响应头:Accept-Ranges: bytes,有这个响应头的,就表示当前响应的资源支持范围请求。
假设一个文件很大,我们想要获取其中的一部分,这个时候就可以使用范围请求了。范围请求常用语实现以下功能更:
看视频,拖到某一个时间点进行加载;
下载工具中的多线程分段下载;
下载工具中高端断点续传,如果网络不好,断开连接了,等到重新连接之后,可以继续获取剩余部分内容。
范围请求头确定了服务端支持范围请求之后,客户端在请求中使用Range请求头,指定要接收的范围即可,如:
-- 格式:bytes=x-y,x y表示偏移量,从0开始 -- 请求获取前面11个字节 Range: bytes=0-10 -- 请求所有内容 Range: bytes=10- -- 获取文档最后10个字节 Range: bytes=-10 服务端响应请求范围不合法,返回状态码416: Range Not Satisfiable;
请求合法,返回状态码206: Partial Content;
响应头添加:Content-Range: bytes x-y/length,表示本次实际响应的范围
举个例子,我们请求IT宅首页,如下:
# 执行以下请求: curl -i -H 'Range: bytes=0-15' https://www.itzhai.com # 结果如下: HTTP/1.1 206 Partial Content Server: nginx/1.16.1 Date: Sun, 30 Aug 2020 02:22:59 GMT Content-Type: text/html Content-Length: 16 Last-Modified: Fri, 01 May 2020 03:45:21 GMT Connection: keep-alive ETag: "5eab9b51-134ee" Content-Range: bytes 0-15/79086 <!DOCTYPE html> 多段数据范围请求支持同时请求多段数据,下面是一个例子:
# 执行以下请求: curl -i -H 'Range: bytes=0-15, 16-26' https://www.itzhai.com # 结果如下: HTTP/1.1 206 Partial Content Server: nginx/1.16.1 Date: Sun, 30 Aug 2020 02:27:07 GMT Content-Type: multipart/byteranges; boundary=00000000000000000023 Content-Length: 228 Last-Modified: Fri, 01 May 2020 03:45:21 GMT Connection: keep-alive ETag: "5eab9b51-134ee" --00000000000000000023 Content-Type: text/html Content-Range: bytes 0-15/79086 <!DOCTYPE html> --00000000000000000023 Content-Type: text/html Content-Range: bytes 16-26/79086 <html class --00000000000000000023--响应格式如下:
4.3、HTTP/1.1连接管理说到HTTP的连接,就不得不先说说TCP的连接管理了,我们来回顾下TCP的建立连接,传输数据,关闭连接的过程:
这里详细流程就不说了,详细参考我的上一篇关于网络内功心法的文章。
可以发现为了传输数据,三次握手和四次挥手,分别消耗了1.5个RTT和2个RTT(Round-trip time RTT),假设建立起这个TCP连接就为了来回传输一次数据,可以发现其利用率很低:
1 / (1 + 1.5 + 2) = 22%
4.3.1、短连接的弊端如下图: