[http协议入门:https://www.ruanyifeng.com/blog/2016/08/http.html]([https://www.ruanyifeng.com/blog/2016/08/http.html](https://www.ruanyifeng.com/blog/2016/08/http.html))
## HTTP工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
1. **客户端连接到Web服务器**
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接
2. **发送HTTP请求**
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成
3. **服务器接受请求并返回HTTP响应**
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. **释放连接 TCP连接**
若connection 模式为close,则服务器主动关闭[TCP连接](https://www.jianshu.com/p/ef892323e68f),客户端被动关闭连接,释放[TCP连接](https://www.jianshu.com/p/ef892323e68f);若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. **客户端浏览器解析HTML内容**
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
## HTTP响应头的 Content-Type字段
头信息必须是ASCII码,数据部分可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式的,这就是Content-Type字段的作用。如`text/html`,`text/css`,`application/javascript`等
客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式`Accept:*/*`;
## Content-Encoding字段
由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法
```
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
```
客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。`Accept-Encoding: gizp, deflate;`
## 持久连接
HTTP1.1引入了持久连接,即TCP连接默认不关闭,可以被多个请求复用,不用声明`Connection:keep-alive`.
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过规范的做法是,客户端在最后一个请求时,发送`Connection: close`,明确要求服务器关闭TCP连接
## 管道机制
1.1 版还引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。
## Content-Length字段
一个TCP连接现在可以传送多个回应,势必就要有一种机制,区分数据包是属于哪一个回应的。这就是`Content-length`字段的作用,声明本次回应的数据长度。
```
Content-Length: 3495
```
上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。
在1.0版中,`Content-Length`字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。
## 分块传输编码
使用`Content-Length`字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。
对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。
因此,1.1版规定可以不使用`Content-Length`字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有`Transfer-Encoding`字段,就表明回应将由数量未定的数据块组成。
每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了