背景
http 协议究竟是什么东西,为什么我们需要去学习它?
其实在平时的开发工作中,http 无处不在。往小来说,当遇到一些发送请求失败,服务端返回错误时,却不知道究竟是什么原因导致的;往大来说,我们在进行架构设计,系统运维,系统测试时,都离不开对 http 的认识。比如客户端请求的各种 api,都是 http 与 xml(或者json)的结合。所以系统地去学习一下 http 协议是有必要的。
浏览器背后的故事
举个例子,当我们在浏览器输入百度 url 地址,就能访问到百度的页面呢?在这个过程中,浏览器都做了什么?这里先引出两个概念:域名 和 ip 地址。
域名就是通过一串用点分隔的名字组成的在 internet 上的某台计算机的名称,用于对计算机的定位标识。比如我们平时输入的 www.baidu.com,就是一个域名。但是计算机在网络上的真正用来作为标识并不是域名,而是一串数字,如百度的 ip 地址 http://202.108.22.5,我们称之为ip。
其实,当我们去访问百度时,浏览器并不是去根据域名去查找百度的服务器,而是浏览器通过 DNS 服务器把域名转换成映射的 ip 地址,然后再去互联网上查找百度的服务器的 ip 地址进行数据请求,而发送请求和响应数据的过程中,使用的正是 http 协议。如下图。
什么是http协议
了解完上面的浏览器访问过程,那什么是 http 协议呢??
http 协议(超文本传输协议)是一种通信协议,它允许将超文本标记语言(html)文档从 Web 服务器传送到客户端浏览器。http 是一个属于应用层的面向对象的协议,由于其便捷、快速的方式,适用于分布式超媒体信息系统。
:::info 提示:文本是带有图文的文档,而超文本就是带有超链接的文本,当点击超链接就能跳转到其他内容的文本。 :::
http协议的发展历程
- 1990年10月,万维网之父 TimBerners-Lee(后简称Tim)最早提出了 http 协议,包括命名方案uri、通讯协议http、用来表达信息的标志语言html,根据这些设想,他实现了一个web客户端和服务器;
- 1991年,Tim 写了一篇关于http协议的文章,现在都称之为 http0.9 版本(这篇文章却很难成为一个协议,因为它并非出自标准化组织,只是 Tim 的个人作品,用来解释他之前实现程序里的通信过程,不过人们为了感谢于 Tim 对万维网的贡献,所以把这篇文章作为 http0.9 版本);
- 在接下来的一段时间里,http 经历了快速发展和混乱的时期,因为 http 在初期并不是太完善,不能满足各种的应用场景,很多公司在此基础上做了很多扩展,但是这些扩展并不能彼此兼容;1994年,Tim 离开了 Sum 公司,成立了 w3c 组织,致力于 html 标准化工作;同年一个叫 IETF 组织成立 http 工作组,研究改进当时的 http;
- 1996年5月,http1.0发布(RFC1945);
- 到了1997年1月,http1.1 第一个版本(RFC2068)发布;
- 1999年6月,http1.1 第二个版本(RFC2616)发布取代了第一个版本,进入一个相对稳定的时期,这也是我们现在用得最多的版本;
- 2015年5年,提出 http2.0(RFC7540)协议,http2.0 主要目标是提高传输性能,实现低延迟和高吞吐量,并没有改变 http1.1 的语义、方法、头部信息等信息,所以我们通常认为 http2.0 是 http1.1 的扩展;
- http3.0协议提出(涉及到QUIC协议),但还没得到市场认可,暂时了解。。。
透过TCP/IP看http
为了深入理解 http 协议,我们有必要先了解 tcp/ip 协议族。http 协议是构建在 tcp/ip 协议之上的,是 tcp/ip 的一个子集,接下来我们仅仅了解一下 http 协议对应的需要掌握的 tcp/ip 协议族的概要。
计算机设备之间可以相互通讯,依赖的是双方基于相同的规则,比如一方先发起通信,另一方怎么接收信息,使用什么语言来进行通信,怎么结束通信等等,这些规则都需要事先确定,我们把这些规则统称为协议。。
tcp/ip 协议其实是一系列与互联网相关联的协议集合起来的总称。在 tcp/ip 协议族里面,分层管理是它的重要特征。tcp/ip 协议族是由一个四层协议组成的系统,这四层分别为:应用层、传输层、网络层和数据链路层。
应用层
应用层一般是我们编写的应用程序,决定了向用户提供的应用服务。应用层可以通过系统调用与传输层进行通信。如:FTP、DNS、HTTP等。
传输层
传输层通过系统调用向应用层提供处于网络连接中的两台计算机之间的数据传输功能。在传输层有两个性质不同的协议:TCP 和 UDP。TCP 是面向连接的,UDP 是无连接的。TCP 因为需要建立连接,可靠性高,但也因为需要连接,导致效率低,UDP 则与之相反。
网路层
网络层是用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位,该层规定了通过怎样的路径(传输路线)到达对方计算机,并把数据包传输给对方。
链路层
链路层用来处理连接网络的硬件部分,包括控制操作系统、硬件设备驱动、NIC(Network Interface Card,网络适配器)以及光纤等物理可见部分。硬件上的范畴均在链路层的作用范围之内。
http数据的封装过程
客户端用户发送的数据需要经过各层进行头部信息的封装才能在网络上进行传输。封装过程如下,每一层都会在上一层的基础上加上自己的头部信息,链路层还会加上尾部信息,最终为数据到达网络提供必要信息。
http 数据的传输过程
客户端发送数据时,数据会从上层传输到下层,且每经过一层都会被打上该层的头部信息。而接收端接收数据时,数据会从下层传输到上层,传输前会把下层的头部信息删除。
传输层-TCP三次握手
前面我们说过,tcp 是面向连接的,那么 tcp 的这个连接过程是怎样的?
使用 tcp 协议进行通信的双方必须先建立连接,然后才能开始传输数据。为了确保连接双方可靠性,在双方建立连接时,tcp协议采用了三次握手策略。
- 第一次握手:客户端发送带有SYN标志的连接请求报文段,然后进入SYN_SEND状态,等待服务端的确认;
- 第二次握手:服务端接收到SYN报文段后,需要发送ACK信息对这个SYN报文段进行确认。同时,还要发送自己的SYN请求信息。服务端会将上述的信息放到一个报文段(SYN+ACK报文段)中,一并发送给客户端,此时服务端将会进入SYN_RECV状态;
- 第三次握手:客户端接收到服务端的SYN+ACK报文段后,会向服务端发送ACK确认报文段,这个报文段发送完毕后,客户端和服务端都进入Established 状态,完成TCP三次握手。
这里,可能有些疑惑,为什么一定要是三次握手呢?
三次握手的最根本目的是客户端和服务端要进行连接,那双方都需要明确对方的收发能力是正常的。这里我们举个简单的例子来说,小A和小B都有一个手机,他们都想测试一下自己手机短信的收发功能是否正常,这两个人一个在北京,一个在上海,互相看不见,所以就有以下步骤:
- 小A先给小B发了一条短信,说:你能收到我的短信吗?收到回复666;
- 过了一段时间,小B收到了小A发的短信,这时小B就知道小A手机发送短信的功能是正常的,小B自己的手机接收短信的功能是正常的;小B这时想知道自己的发送短信功能是否正常,小B就回复了:我收到你的信息啦,666,那你能收到我的信息吗?收到给我回复777;
- 过了一段时间后,小A也收到了小B的短信(其实在没接收到小B的短信之前,小A是不知道自己的手机短信是否发送成功的),那小A就知道自己第一次发送的短信肯定是成功的,不然小B不会给自己回复信息(即小A知道自己的发送功能是正常的,小B的接收信息和发送信息是正常的);但这个时候小B仍然不知道自己手机的发送短信是否成功,小A的接收短信能力是否正常,所以小A还需要回复一下小B;
- 小A就回复了一个短信:我收到信息啦,777。当小B接收到信息之后,这时小B就可以确认了自己的短信发送能力,小A的接收短信能力都是正常的。
DNS域名解析
上面我们说到 http 协议与 tcp/ip 协议有密切关系,但除了 tcp/ip 之外,DNS 服务与 http 协议也有着密不可分的关系。
通常我们访问一个网站,使用的是主机名或者域名来进行访问的。因为相对于 ip 地址(一组纯数字),域名更容易让人记住。但 tcp/ip 协议使用的是 ip 地址进行访问的,所以必须有个机制或者服务把域名转换成 ip 地址。dns 服务就是用来解决这个问题的,它提供域名到 ip 地址之间的解析服务,这是从宏观的角度来说。
从微观的角度来说,为了提高效率,dns 服务的解析是有层次的,采取的是就近原则。首先我们本地电脑会将一些经常使用的域名和响应的 ip 地址建立一个映射关系并且保存到系统文件里面,所以正常情况下,在进行 dns 解析时,系统会优先从系统文件里查找 ip 地址,如果找到就直接使用 host 文件里面的 ip 地址,如果没有就查找本地的 dns 服务器(tcp/ip的参数里面的首选 dns 服务器,即我们电脑中设置网络适配器时设置的首选dns服务器,如:8.8.8.8/114.114.114.114),如果还没有,就一层一层地继续往上查找,直到 dns 根服务器,如果都没有那就返回这个域名不存在。
http事务处理过程
联系前面的内容,我们可以了解到整个 http 事务处理过程是这样子的。
当客户端访问 web 站点时,首先会通过 dns 服务查询到域名的 ip 地址。然后浏览器生成 http 请求,并通过 tcp/ip 协议发送给 web 服务器。web 服务器接收到请求后会根据请求生成响应内容,再通过 tcp/ip 协议返回给客户端。
使用wireshark进行一次网络请求抓取
这里我们以 http://fanyi.youdao.com/ 地址为例,当我们去访问这个地址后,可以看到整个 tcp 过程中,首先从本地(53764)发送了一个 SYN 到 youdao.com(80),然后 youdao.com(80)返回了 SYN+ACK 给本地,最后本地(53764)再次发送 ACK,建立连接完成。
接着,我们在输入框输入一些内容,可以看到本地(10.0.101.53)给服务端(220.181.76.83)发送了一个 http 请求,服务端(220.181.76.83)给本地(10.0.101.53)返回了一个 http 响应,而且返回消息类型是 json。
同时,我们也可以在浏览器的 network 中看到请求发送内容。
总结
- http 协议是在tcp/ip 协议族里面的一个子集;
- tcp/ip 协议族里面有着严格的交流规则,即http封装数据;发送端从上往下逐层添加头部信息进行传递,接收端从下往上逐层去掉头部信息进行接收;
- http 和传输层的 tcp 紧密关联,所以每次连接时都需要进行三次握手;
- tcp/ip 是通过 ip 地址进行访问的,所以需要通过 dns 服务器将域名转换为 ip 地址。
to be continue….