HTTP协议
Http
协议构建于tcp/ip
协议之上,是一个应用层协议,默认的端口是80
;HTTP
无连接、无状态。
HTTP报文
HTTP
是以ASCII
码进行传输,建立在tcp/ip
协议上的应用层规范。规范把http
的请求分为三个部分:状态行、头部、主体
Request请求
请求分为三个部分:状态行、头部、主题(可选)
<Method> <request-url> <version>
<Headers>
<entity-body>
Method
:请求方法
GET
:从服务器获取资源PUT
:写入文档Head
:只获得首部POST
:发送数据,如表单Delete
:删除Options
:查看服务器支持的请求方法Trace
:报文追踪
request-url
:请求资源的地址,url
一般包含几个部分:协议、主机、端口、URI
version
:HTTP
协议版本Headers
:请求头部Body
:请求主体
Response返回数据
返回分为三个部分:状态行、头部、主题(可选)
<Version> <status> <reason-phrase>
<Headers>
<entity-body>
version
:服务器协议版本status
:返回状态码。每个状态码都有不同的含义
200
:请求成功301
:永久重定向302
:临时重定向304
:资源未修改400
:请求错误401
:未认证403
:没有权限404
:无该资源500
:服务器内部错误502
:网关或者代理从服务器收到一个无效的响应504:
网关或代理超时
reason-phrase
:原因短语。如:timeout
等headers
:返回头部entity-body
:返回主体/内容
注意:
4xx
状态码一般为客户端错误5xx
状态码一般为服务端错误
HTTP长链接
HTTP
采用请求<——>应答
模式,当使用非keep-alive
模式时,每次请求,客户端和服务端都要建立一个新的连接,完成之后立即断开连接(无状态)。
当使用keep-alive
模式时,keep-alive
使两端的连接长期有效,请求完成后,连接不会立马断开,当C有后续请求时,可直接使用此连接,不用再进行三次握手。减少开销。
HTTP 1.0版本
- 在
http 1.0
版本中,需要显示指定头部来创建长链接。 - 头部:
Connection: keep-alive
(客户端和服务端都需要指定)
HTTP 1.1版本
- 在
http 1.1
版本中,默认为长链接,不需要额外指定头部。但如果不想保持长链接,可指定头部关闭。 - 头部:
Connection: close
注意:
- 目前绝大多数浏览器都是
HTTP 1.1
版本 HTTP
的keep-alive
简单来说就是保持当前的tcp
连接- 长链接不可能一直保持,如:
keep-alive: timeout=5,max=100
,这表示这个tcp
连接通道可以保持5s
,最多接收100次
请求。然后就会断开连接了 HTTP
是一个无状态协议,keep-alive
也不能保证C和S之间的连接是活跃的,HTTP 1.1
版本也是如此。唯一能保证的就是当前连接被关闭时你能得到一个通知。So,不要让程序依赖于keep-alive
的保持连接特性,否则会有意想不到的隐患- 使用长链接之后,C或者S怎么知道本次传输结束了呢?
- 判断数据是否达到了
Content-Length
的大小 - 使用
chunked
编码进行判断。动态生成的文件没有Content-Length
头部,它是分块传输,chunked
编码数据在最后有一个空chunked
块,表示本次传输结束。但在HTTP 2.0
版本中不用此特性,HTTP 2.0
自带流式传输
Transfer-Encoding头部
Transfer-Encoding
是一个用来标记HTTP
报文传输格式的头部。尽管理论上这个值可以有很多,但是当前的HTTP规范
里实际上只定义了一个值——chunked
如果一个HTTP
消息的Transfer-Encoding
值为chunked
,那么,消息体是由数量未定的块组成的,并以最后一个大小为0
的块结束
每一个非空的块都以该块包含数据的字节数开始(十六进制),跟随一个CRLF
(回车及换行),然后是数据本身。
注意:
chunked
传输不能事先知道内容的长度,只能靠最后的空块进行判断,因此对于下载请求来说,是没有办法看到下载进度的chunked
的优势在于,服务端可以边生成内容边发送HTTP 2.0
版本不支持chunked
,因为HTTP 2.0
有自己的streaming
传输方式
HTTP跨域
跨域资源共享(CORS
)是一种机制,它使用额外的http头部
来告诉浏览器,让运行在一个orgin
上的web
应用被准许访问来自不用源服务器上的指定资源。
当一个资源从与该资源本身所在的服务器不同的域、协议、端口
请求一个资源时,资源会发起一个跨域HTTP请求
简单跨域
简单跨域请求满足的要求:
- 请求方法是以下
3
种之一
HEAD
GET
POST
HTTP
头部信息不超出以下几种字段
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
:只限于三个值application/x-www-form-urlencoded、text/plain、mutiport/form-data
复杂跨域请求
负载跨域请求会产生两次http
请求,一次预检查请求(options
),一次跨域请求;服务端需要对这两次请求都要做跨域支持
预检查请求:主要是提前检查服务器对请求方法、头是否支持
如何处理跨域请求?
分为以下三种情况:
- 服务端没有对跨域进行支持
- 服务器添加跨域相关的
Header
- 客户端带来跨域允许之外的头部
- 客户端去除多余的头部
- 服务端加上多余头部支持
- 由于缓存导致跨域不允许,常见于对静态资源的访问
- 无视缓存,前段为每一个文件加上时间戳,直接回源访问
- 如果是浏览器本地缓存导致,需检查前端代码(是否有
2
次请求) - 浏览器之外所有导致问题的缓存,只有挨个排查了
跨域相关的Header
头部 | 说明 |
---|---|
Access-Control-Allow-Origin: | * | 允许指定域的请求 |
Access-Control-Allow-Methods: | 允许的请求方法 |
Access-Control-Allow-Headers:
| 允许携带的头部 |
Access-Control-Allow-credentials: true | 允许携带Cookie |
MTU和MSS的区别
MTU: Maximum Transmit Unit
,最大传输单元,即物理接口(数据链路层
)提供给上层(IP层
)最大一次传输数据的大小;以普遍使用的以太网为例,默认MTU=1500Byte
,这是以太网接口对IP
层的约束。
如果IP
层有<= 1500 Byte
的数据需要发送,只需要一个IP包
就可以完成任务。如果有> 1500 Byte
的数据需要发送,需要分片才能完成发送,但这些分片都具有一个特点——IP Header ID相同
MSS:Maximum Segment Size
,最大分段大小。布包含tcp header
和tcp options
,MSS
是tcp
用来限制应用层最大发送的字节数。如果MTU = 1500
,那么MSS = 1500 - 20(tcp header) - 20(tcp options) = 1460
总结
本篇文章介绍了关于HTTP
协议的请求、响应、头部、编码、跨域、长链接、MSS、MTU等等。有经验的开发者应该都知道,在HTTP
层的很多功能,如长链接、缓存、编码等都是通过HEADER
来实现的,所以Header
在HTTP
里面承担了非常重要的角色。
Header Header Header Header Header Header Header Header Header Header Header