我的更多文章可访问:https://zhangzw.com/

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的网络协议。是一种建立在TCP上的无状态连接,整个基本的工作流程是客户端发送一个HTTP请求,说明客户端想要访问的资源和请求的动作,服务端收到请求之后,服务端开始处理请求,并根据请求做出相应的动作访问服务器资源,最后通过发送HTTP响应把结果返回给客户端。

HTTP发展史

HTTP发展过程已经演化出了很多版本,它们中的大部分都是向下兼容的。其中主要的三个版本分别是:HTTP/1.0、HTTP/1.1、HTTP/2.0。

HTTP/1.0

HTTP/1.0最大的改变是引入了POST方法,使得客户端通过HTML表单向服务器发送数据成为可能,这也是WEB应用程序的一个基础。

另一个巨大的改变是引入了HTTP头,使得HTTP不仅能返回错误代码,并且HTTP协议所传输的内容不仅限于纯文本,还可以是图片,动画等一系列格式。

除此之外,还允许保持连接,既一次TCP连接后,可以多次通信,虽然HTTP/1.0 默认是传输一次数据后就关闭。

HTTP/1.1

2000年5月,HTTP/1.1确立。HTTP/1.1并不像HTTP/1.0对于HTTP/0.9那样的革命性。但是也有很多增强。

变化如下:

  • 缓存处理:

    在HTTP/1.0中主要使用了if-modified-since 和 expires,而在HTTP/1.1中出现了跟多的缓存控制策略,例如Entity-tag、If-Unmodified-since、If-Match、if-none-match。

  • 带宽优化以及网络连接的使用:

    在HTTP/1.0中,存在着一些带宽浪费,譬如,一些用户只想请求某个对象的一部分内容,而服务器却将整个内容都发送了过来,并且不支持断点续传功能,而HTTP/1.1在请求头部引入了range头,它允许请求资源的某个部分,返回码为206(Partial Content),此种做法方便了开发者调试以及合理的利用带宽资源

  • 错误通知的管理:

    在HTTP/1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

  • Host头处理:

    在HTTP/1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP/1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)

  • 长连接:

    HTTP/1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP/1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP/1.0每次请求都要创建连接的缺点。

HTTP/2.0

增加的新特性:

  • 新的二进制格式(Binary Format)

    HTTP/1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP/2.0的协议解析决定采用二进制格式,实现方便且健壮。

  • 多路复用(MultiPlexing)

    即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的id将request再归属到各自不同的服务端请求里面。

  • Header压缩

    HTTP/1.x的header带有大量信息,而且每次都要重复发送,要知道上行带宽是很珍贵的,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  • 服务端推送(Server Push)

    同SPDY一样,HTTP/2.0也具有server push功能。

HTTP/2.0在线测试:https://servertest.online/http2

HTTP网络层次

先来个高清大图:

详解HTTP协议基础

详解HTTP协议基础

可以看出,HTTP是基于传输层的TCP协议,而TCP是一个端到端的面向连接的协议。所谓的端到端可以理解为进程到进程之间的通信。所以HTTP在开始传输之前,首先需要建立TCP连接,而TCP连接的过程需要所谓的“三次握手”。

在TCP三次握手之后,建立了TCP连接,此时HTTP就可以进行传输了。一个重要的概念是面向连接,既HTTP在传输完成之前并不断开TCP连接。

HTTP报文格式

HTTP请求

HTTP请求,即Web客户端向Web服务器发送信息,这个信息由如下三部分组成:

  1. 请求行
  2. HTTP头,又分:
    1. 请求头(Request Header)
    2. 普通头(General header)
    3. 实体头(Entity header)
  3. 内容
    详解HTTP协议基础

HTTP响应

当Web服务器收到HTTP请求后,会根据请求的信息做某些处理,相应的返回一个HTTP响应。HTTP响应在结构上很类似于HTTP请求,也是由三部分组成,分别为:

  1. 状态行
  2. HTTP头,又分:
    1. 响应头(Response Header)
    2. 普通头(General header)
    3. 实体头(Entity header)
  3. 返回内容
    详解HTTP协议基础

关于HTTP头

HTTP头并不是严格要求的,仅仅是一个标签,如果浏览器可以解析就会按照某些标准(比如浏览器自身标准,W3C的标准)去解释这个头,否则不识别的头就会被浏览器无视。对服务器也是同理。假如你编写一个浏览器,你可以将上面的头解释成任何你想要的效果。

通用头(General header)

通用头即可以包含在HTTP请求中,也可以包含在HTTP响应中。通用头的作用是描述HTTP协议本身。比如描述HTTP是否持久连接的Connection头,HTTP发送日期的Date头,描述HTTP所在TCP连接时间的Keep-Alive头,用于缓存控制的Cache-Control头等。

实体头(Entity header)

实体头是那些描述HTTP信息的头。既可以出现在HTTP POST方法的请求中,也可以出现在HTTP响应中。比如Content-Type和Content-length都是描述实体的类型和大小的头都属于实体头。其它还有用于描述实体的Content-Language,Content-MD5,Content-Encoding以及控制实体缓存的Expires和Last-Modifies头等。

请求头(Request Header)

请求头是那些由客户端发往服务端以便帮助服务端更好的满足客户端请求的头。请求头只能出现在HTTP请求中。比如告诉服务器只接收某种响应内容的Accept头,发送Cookies的Cookie头,显示请求主机域的HOST头,用于缓存的If-Match,If-Match-Since,If-None-Match头。用于只取HTTP响应信息中部分信息的Range头,用于附属HTML相关请求引用的Referer头等。

响应头(Response Header)

HTTP响应头是那些描述HTTP响应本身的头,这里面并不包含描述HTTP响应中第三部分也就是HTTP信息的头(这部分由实体头负责)。比如说定时刷新的Refresh头,当遇到503错误时自动重试的Retry-After头,显示服务器信息的Server头,设置COOKIE的Set-Cookie头,告诉客户端可以部分请求的Accept-Ranges头等。

Get和Post区别

网上关于Get和Post的区别满天飞,但大多没有说到点子上。Get和Post最大的区别就是Post有上面所说的第三部分:内容。而Get不存在这个内容。因此就像Get和Post其名称所示那样,Get用于从服务器上取内容,虽然可以通过QueryString向服务器发信息,但这违背了Get的本意,QueryString中的信息在HTTP看来仅仅是获取所取得内容的一个参数而已。而Post是由客户端向服务器端发送内容的方式。因此具有请求的第三部分:内容。

常见的状态码

200—OK/请求已经正常处理完毕

301—/请求永久重定向

302—/请求临时重定向

304—/请求被重定向到客户端本地缓存

400—/客户端请求存在语法错误

401—/客户端请求没有经过授权

403—/客户端的请求被服务器拒绝,一般为客户端没有访问权限

404—/客户端请求的URL在服务端不存在

500—/服务端永久错误

502—/网关或代理错误

503—/服务端发生临时错误

常见的请求头

Header 解释 示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: [email protected]
Host 指定请求的服务器的域名和端口号 Host: www.zhangzw.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zhangzw.com
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

三次握手&四次挥手

详解HTTP协议基础

三次握手:

  1. 第一次握手:

    客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;

  2. 第二次握手:

    服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  3. 第三次握手:

    客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

四次挥手:

  1. 第一次挥手:

    主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可以接受数据。

  2. 第二次挥手:

    被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。

  3. 第三次挥手:

    被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。

  4. 第四次挥手:

    主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

参考资料

https://www.cnblogs.com/zhangtaotqy/p/9408834.html

https://blog.51cto.com/13570193/2108347

https://blog.csdn.net/zhangyexinaisurui/article/details/82711848

https://blog.csdn.net/ccpat/article/details/79413433

http://en.wikipedia.org/wiki/HTTP/2#Browser_support

相关文章:

  • 2021-10-27
  • 2021-07-03
  • 2022-12-23
  • 2022-12-23
  • 2021-10-12
  • 2021-08-14
  • 2022-01-17
猜你喜欢
  • 2021-07-02
  • 2021-04-14
  • 2021-09-14
  • 2021-08-22
  • 2022-12-23
  • 2022-01-04
  • 2022-02-03
相关资源
相似解决方案