这篇博客主要介绍http协议相关的内容,总结了从浏览器的地址栏输入一个地址到获得请求的网页,经历了什么?以及对各版本http的特点进行总结。
从浏览器的地址栏输入一个地址到获得请求的网页,后端经历了什么?
例如,我们键入: http://www.163.com,首先浏览器会将这个域名发送给DNS服务器,让它解析成IP地址。接着,因为HTTP是基于TCP的,因此要先建立TCP连接。于是三次握手四次挥手建立了TCP连接。(注意:目前使用的HTTP协议大多是1.1的在1.1里默认开启了Keep-Alive,这样建立的TCP连接,可以在多次请求中反复使用。)
接着我们拼凑起一个http请求报文。(通常包括:请求行,请求头,请求实体)。接下来交给Socket去发送,再交给TCP层。将报文二进制流变成一个个的报文发送。(在发送每一个报文的时候都需要对方回应一个ACK来保证报文到达,如果没有回应,那么TCP这一层会进行重新传输,知道可达,但是HTTP这一层不知道这点。)TCP在报文上加上自己的地址(原地址)和目标地址将这两个信息放至IP头,交给IP头传输。
IP层查看目标地址是否在同一个局域网,若时则发送ARP协议来请求这个目标地址的MAC地址,然后将源MAC地址和目标MAC地址放入MAC头交给链路层即可。若不在同一个局域网就发送到网关,计将源MAC地址和网关MAC地址放入MAC头发送出去。网关收到包发现MAC符合,取出目标IP地址,根据路由协议找到下一跳路由器获取下一跳路由器MAC地址,将包发送给下一跳路由器。
这样最终到达目标局域网,再到达目标地址。目标机器发现MAC符合,就将包收起来,发现IP地址符合再解析TCP头里面有序列号,看是否是所需要的,是就返回一个ACK,否则就丢弃。TCP头还有端口号,HTTP服务器正在监听这个端口号。于是目标机器知道是HTTP服务器这个进程想要这个包,就将包发送给HTTP服务器,HTTP进程拿到这个包后发现这是个要请求网页的请求包就将这个网页发送给客户端。
返回的过程类似。当浏览器拿到了HTTP报文,发现返回200,一切正常,于是就从正文中将HTML拿出来。后面浏览器就开始渲染这个网页。
(关于拿到这个网页后浏览器如何渲染,见浏览器内部机制)
HTTP各版本协议间的区别及特点。
版本version | HTTP1.0 | HTTP1.1 | HTTP2.0 |
---|---|---|---|
连接 | 无连接,无法复用 | 长连接(Keep-Alive) | 长连接 |
是否跟踪状态 | 无状态 | 跟踪状态 | 跟踪状态 |
其它特点 | 请求管道化 加入缓存处理(cache-control) 支持断点传输 增加Host字段如果第一个请求被堵塞了,则后面的请求即使处理完毕了,也需要等待 | 所有通信都在一个 TCP 连接上完成。支持服务器到客户端的主动推送机制 浏览器可以指定每个流的优先级,让服务器决定最优的响应次序 header压缩 二进制分帧 对HTTP头进行压缩 连接共享(分流,分帧(携带stream id辨识属于哪个请求流)解决队首阻塞,实现了真正的并行传输) | |
缺点 | 无法复用连接 | 无法并行(只能通过打开多个TCP会话) | 多路复用(连接共享)可能会导致关键请求被阻塞 问题: 优先级问题(存在资源抢占), 丢失重复发包问题 |
💡注:
由于http2的多路复用,合并请求显得不是很必要:
如:jS文件的合并。我们现在优化的一个主要方向就是尽量的减少HTTP的请求数, 对我们工程中的代码,研发时分模块开发,上线时我们会把所有的代码进行压缩合并,合并成一个文件,这样不管多少模块,都请求一个文件,减少了HTTP的请求数。但是这样做有一个非常严重的问题:文件的缓存。当我们有100个模块时,有一个模块改了东西,按照之前的方式,整个文件浏览器都需要重新下载,不能被缓存。现在我们有了HTTP/2了,模块就可以单独的压缩上线,而不影响其他没有修改的模块。
因此有关http2下的性能优化方案可能需有所调整。
- HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
- HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
http编码
- ASCII码: http报文基于ASCII码(文本协议),原因:二进制协议可读性差,调试困难,对于一些数字,二进制传输Server是没法处理的。
- base64: 一种基于64个可打印字符来表示二进制数据的编码方法。因为输入的字符可能有ASCII码中不可见字符,为完全可见,就用了base64编码。(二进制图片 → 文本)
- MIME: 能对包含文本、图像、音频、视频以及其他应用程序专用的数据 编码
举例用过的:text/html
(超文本标记语言文本)image/gif
image/jpeg
text/plain
(普通的文本)video/mpeg
(MPEG文件)
注意: 如果直接使用http传输二进制的问题?不知道传输字节的具体长度。对于一些数字,二进制传输Server是没法处理的。可能会与终止符和冲突重复。
HTTP Header
-
General Header
- Request URL
- Request Method
- Status Code
- Remote Address
- Referrer Policy(用于过滤 Referrer 报头内容):
no-referrer-when-downgrade
(当发生降级(比如从 https:// 跳转到 http:// )时,不传递 Referrer 报头。但是反过来的话不受影响。通常也会当作浏览器的默认安全策略)
-
Request Header
- Accept(能够接受的内容类型):
*/*
text/plain, text/html
- Accept-Encoding(能够接受的编码类型):
gzip, deflate, br
- Accept-Language:
zh-CN,zh;q=0.9
- Accept-Ranges (可以请求网页实体的一个或者多个子范围字段):
Accept-Ranges: bytes
- Authorization(HTTP授权的授权证书):
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- Cache-Control:
max-age=2592000
- Connection(表示是否需要持久连接。(HTTP 1.1默认进行持久连接)):
keep alive
- Cookie:
_ga=GA1.2.764928072.1522162861
- Content-Length(请求的内容长度):
Content-Length: 348
- Content-Type(请求的与实体对应的MIME信息):
text/plain; charset=utf-8
image/png
application/x-www-form-urlencoded
- Date(请求发送的日期和时间):
Sun, 24 Mar 2019 08:20:11 GMT
- Expect(请求的特定的服务器行为):
100-continue
- From(发出请求的用户的Email):
user@email.com
- Host (指定请求的服务器的域名和端口号):
www.zcmhi.com
- If-Match
- If-Modified-Since
- If-None-Match
- Pragma(用来包含实现特定的指令): no-cache
- Proxy-Authorization(连接到代理的授权证书):
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- Range(只请求实体的一部分,指定范围):
bytes=500-999
- Referer(先前网页的地址,当前请求网页紧随其后,即来路)
- Upgrade: 向服务器指定某种传输协议以便服务器进行转换(如果支持):
HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 websorket
- User-Agent:
Mozilla/5.0 (Linux; X11)
- Via(通知中间网关或代理服务器地址,通信协议):
1.0 fred, 1.1 nowhere.com (Apache/1.1)
- Accept(能够接受的内容类型):
-
Response
- Accept-Ranges(表明服务器是否支持指定范围请求及哪种类型的分段请求):
bytes
- Age(从原始服务器到代理缓存形成的估算时间(以秒计,非负)): 12
- Access-Control-Allow-Origin
- Access-Control-Allow-Credentials(表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。表示是否允许发送Cookie,跨域时客户端withCredentials 为 true 的请求会带上cookie)
- Access-Control-Allow-Headers
- Access-Control-Allow-Methods
- Access-Control-Max-Age
- Allow(对某网络资源的有效的请求行为,不允许则返回405):
GET, HEAD
- Cache-Control
- Content-Encoding:
gzip
- Content-Language:
en,zh
- Content-Length
- Content-Location(请求资源可替代的备用的另一地址):
/index.htm
- Content-MD5(返回资源的MD5校验值):
Q2hlY2sgSW50ZWdyaXR5IQ==
- Content-Range(在整个返回体中本部分的字节位置):
bytes 21010-47021/47022
- Content-Type
- Date
- ETag
- Expires
- Last-Modified
- Location(用来重定向接收方到非请求URL的位置来完成请求或标识新的资源)
- Pragma
- Proxy-Authenticate(它指出认证方案和可应用到代理的该URL上的参数):
Basic
- refresh(应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)):
5; url=http://www.zcmhi.com/archives/94.html
- Server(web服务器软件名称):
Nginx
- Set-Cookie:
io=pzIA1o986mOtUp5Xc0B5; Path=/; HttpOnly
- Trailer(指出头域在分块传输编码的尾部存在):
Max-Forwards
- Transfer-Encoding(文件传输编码):
chunked
- Vary(告诉下游代理是使用缓存响应还是从原始服务器请求):
*
- Via
- Accept-Ranges(表明服务器是否支持指定范围请求及哪种类型的分段请求):
http状态码
- 2xx
- 200
- 204: No content. 成功但响应报文不含实体的主体部分
- 205: Reset Content 成功但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
- 206: Partial Content 进行范围请求
- 3xx
- 301: 永久重定向: 表示资源已被分配了新的 URL。搜索引擎机器人会在遇到该状态码时触发更新操作,在其索引库中修改与该资源相关的 URL 。举例: 网站重构, 更换域名,http迁移到https
- 302: 临时重定向: 由于不可预见的原因该页面暂不可用。在这种情况下,搜索引擎不会更新它们的链接。其他方法有可能会变更为 GET 方法.举例: 比如: 登录前先使用302重定向到登录页面,登录成功后再跳回到原来请求的页面。比如: 自动刷新页面,比如5秒后回到订单详细页面之类。
- 303: see other: 表示资源存在着另一个 URL,应使用 GET 方法获取资源。其他方法会变更为 GET 方法.(一些请求的处理会需要比较长的时间,比如有时候 DELETE 请求会被安排为稍后处理。在这种情况下,会返回一个 303 (See Other) 重定向响应,该响应链接到一个页面,表示请求的操作已经被列入计划,并且最终会通知用户操作的进展情况,或者允许用户将其取消。)
- 304: not modified
- 305: Use Proxy 使用代理。所请求的资源必须通过代理访问
- 307: temporary redirect.临时重定向,和302含义类似,但是期望客户端保持请求方法不变向新的地址发出请求。在这种情况下,搜索引擎不会更新它们的链接。当站点支持非 GET 方法的链接或操作的时候,该状态码优于 302 状态码。(也就是换个地址,重复对应的那个请求)
- 308: 与301类似,只不过是针对POST方法的请求不允许更改方法
- 4xx
- 400 bad request 请求报文存在语法错误
- 401 unauthorized 表示发送的请求需要有通过 HTTP 认证的认证信
- 403 forbidden 表示对请求资源的访问被服务器拒绝
- 404 not found
- 405 method not allowed 请求的方式(get、post、delete)方法与后台规定的方式不符合
- 415 后台程序不支持提交的content-type,就会返回415
- 5xx
- 500 internal sever error
- 501 Not Implemented 表示服务器不支持当前请求所需要的某个功能
- 502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
- 503 service unavailable 表明服务器暂时处于超负载或正在停机维护,无法处理请求
- 504 gate way time out
HTTP请求
- 简单请求
- HEAD
- GET
- POST
- http头信息
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type
- 非简单请求
- 预检请求: 比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json
- 浏览器跨域非简单请求头 字段包含
- Access-Control-Request-Method
- Access-Control-Request-Headers(指定浏览器CORS请求会额外发送的头信息字段)
X-Custom-Header
- 服务端做出响应
- Access-Control-Allow-Origin: *
- Access-Control-Allow-Methods: GET, POST, PUT
- Access-Control-Allow-Headers: X-Custom-Header
- Access-Control-Allow-Credentials: true
- Access-Control-Max-Age(用来指定本次预检请求的有效期,单位为秒): 1728000
end
参考:
《趣谈网络协议》(刘超 极客时间)
HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比