1.1通过看新闻熟悉网络
目录介绍
- 01.在浏览器输入链接
- 1.1 输入什么链接
- 1.2 提取链接协议
- 1.3 域名请求解析
- 1.4 Mac和IP地址
- 02.HTTP请求准备
- 2.1 确定请求方法
- 2.2 构建请求URL
- 03.HTTP请求构建
- 3.1 请求报问规范
- 3.2 设置请求行
- 3.3 设置请求头
- 3.4 设置请求体
- 04.HTTP请求发送
- 4.1 建立网络连接
- 4.2 发送请求头
- 4.3 发送请求体
- 4.4 等待服务器响应
- 05.HTTP返回构建
- 5.1 构建响应码
- 5.2 构建响应头
- 5.3 构建响应体
- 5.4 发送响应数据
01.在浏览器输入链接
1.1 输入什么链接
1.2 提取链接协议
1.3 域名请求解析
- HTTP协议,几乎是每个人上网用的第一个协议,同时也是很容易被人忽略的协议。
- 既然说看新闻,咱们就先登录http://www.163.com。http://www.163.com是个URL,叫作统一资源定位符。
- 之所以叫统一,是因为它是有格式的。HTTP称为协议,www.163.com是一个域名,表示互联网上的一个位置。有的URL会有更详细的位置标识,例如http://www.163.com/index.html。正是因为这个东西是统一的,所以当你把这样一个字符串输入到浏览器的框里的时候,浏览器才知道如何进行统一处理。
02.HTTP请求准备
- **浏览器会将www.163.com这个域名发送给DNS服务器,让它解析为IP地址。**有关DNS的过程,其实非常复杂,这里先不管,反正它会被解析成为IP地址。那接下来是发送HTTP请求吗?
- 不是的,HTTP是基于TCP协议的,当然是要先建立TCP连接了,怎么建立呢?还记得三次握手吗?
- 目前使用的HTTP协议大部分都是1.1。在1.1的协议里面,默认是开启了Keep-Alive的,这样建立的TCP连接,就可以在多次请求中复用。
- 学习了TCP之后,你应该知道,TCP的三次握手和四次挥手,还是挺费劲的。如果好不容易建立了连接,然后就做了一点儿事情就结束了,有点儿浪费人力和物力。
2.1 确定请求方法
- 确定请求方法:根据用户在浏览器中的操作(例如点击链接或提交表单),浏览器确定要使用的HTTP请求方法。
- 常见的方法包括GET、POST、PUT、DELETE等。
2.2 构建请求URL
- 构建URL:浏览器将用户输入的URL与当前页面的基本URL进行组合,生成完整的请求URL。
- 这个URL包含了协议、主机名、路径和查询参数等信息。
03.HTTP请求构建
3.1 请求报问规范
- 建立了连接以后,浏览器就要发送HTTP的请求,请求的格式就像这样。
image
- HTTP的报文大概分为三大部分。
- 第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体。
3.2 设置请求行
3.3 设置请求头
3.4 设置请求体
3.1 第一部分:请求行
- 在请求行中,URL就是http://www.163.com,版本为HTTP 1.1。这里要说一下的,就是方法。方法有几种类型呢?
- 对于访问网页来讲,最常用的类型就是GET。顾名思义,GET就是去服务器获取一些资源。对于访问网页来讲,要获取的资源往往是一个页面。其实也有很多其他的格式,比如说返回一个JSON字符串,到底要返回什么,是由服务器端的实现决定的。
- 例如,在云计算中,如果我们的服务器端要提供一个基于HTTP协议的API,获取所有云主机的列表,这就会使用GET方法得到,返回的可能是一个JSON字符串。字符串里面是一个列表,列表里面是一项的云主机的信息。
- 另外一种类型叫做POST。它需要主动告诉服务端一些信息,而非获取。要告诉服务端什么呢?一般会放在正文里面。正文可以有各种各样的格式。常见的格式也是JSON。
- 例如,我们下一节要讲的支付场景,客户端就需要把“我是谁?我要支付多少?我要买啥?”告诉服务器,这就需要通过POST方法。再如,在云计算里,如果我们的服务器端,要提供一个基于HTTP协议的创建云主机的API,也会用到POST方法。这个时候往往需要将“我要创建多大的云主机?多少CPU多少内存?多大硬盘?”这些信息放在JSON字符串里面,通过POST的方法告诉服务器端。
- 还有一种类型叫PUT,就是向指定资源位置上传最新内容。但是,HTTP的服务器往往是不允许上传文件的,所以PUT和POST就都变成了要传给服务器东西的方法。
- 在实际使用过程中,这两者还会有稍许的区别。POST往往是用来创建一个资源的,而PUT往往是用来修改一个资源的。例如,云主机已经创建好了,我想对这个云主机打一个标签,说明这个云主机是生产环境的,另外一个云主机是测试环境的。那怎么修改这个标签呢?往往就是用PUT方法。
- 再有一种常见的就是DELETE。这个顾名思义就是用来删除资源的。例如,我们要删除一个云主机,就会调用DELETE方法。
3.2 第二部分:首部字段
- 请求行下面就是我们的首部字段。
- 首部是key value,通过冒号分隔。这里面,往往保存了一些非常重要的字段。
- 例如,Accept-Charset,表示客户端可以接受的字符集,防止传过来的是另外的字符集,从而导致出现乱码。再如,Content-Type是指正文的格式。例如,我们进行POST的请求,如果正文是JSON,那么我们就应该将这个值设置为JSON。
- 这里需要重点说一下的就是缓存。为啥要使用缓存呢?
- 那是因为一个非常大的页面有很多东西。例如,我浏览一个商品的详情,里面有这个商品的价格、库存、展示图片、使用手册等等。商品的展示图片会保持较长时间不变,而库存会根据用户购买的情况经常改变。如果图片非常大,而库存数非常小,如果我们每次要更新数据的时候都要刷新整个页面,对于服务器的压力就会很大。
- 对于这种高并发场景下的系统,在真正的业务逻辑之前,都需要有个接入层,将这些静态资源的请求拦在最外面,架构图就像这样。
image
- 其中DNS、CDN我在后面的章节会讲。和这一节关系比较大的就是Nginx这一层,它如何处理HTTP协议呢?对于静态资源,有Vanish缓存层。当缓存过期的时候,才会访问真正的Tomcat应用集群。
- 在HTTP头里面,Cache-control是用来控制缓存的。当客户端发送的请求中包含max-age指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定max-age值为0,那么缓存层通常需要将请求转发给应用集群。
- 另外,If-Modified-Since也是一个关于缓存的。也就是说,如果服务器的资源在某个时间之后更新了,那么客户端就应该下载最新的资源;如果没有更新,服务端会返回“304 Not Modified”的响应,那客户端就不用下载了,也会节省带宽。
- 目前为止,我们仅仅是拼凑起来了HTTP请求的报文格式,接下来,浏览器会把它交给下一层传输层。怎么交给传输层呢?其实也无非是用Socket这些东西,只不过用的浏览器里,这些程序不需要你自己写,有人已经帮你写好了。
04.HTTP请求发送
4.1 建立网络连接
- 浏览器使用TCP/IP协议与服务器建立网络连接。这涉及到解析主机名为IP地址、建立TCP连接等步骤。
4.2 发送请求头
- 浏览器将构建好的HTTP请求头发送给服务器。
- 请求头包含了请求方法、URL、请求头字段(如User-Agent、Accept等)等信息。
4.3 发送请求体
- 发送请求体(对于POST请求):
- 如果请求方法是POST或其他需要发送数据的方法,浏览器会将请求体发送给服务器。请求体可以包含表单数据、JSON数据等。
4.4 等待服务器响应
等待服务器响应:浏览器等待服务器对请求作出响应。
- 在等待期间,浏览器可能会显示加载指示器,以表示请求正在进行中。
HTTP协议是基于TCP协议的,所以它使用面向连接的方式发送请求,通过stream二进制流的方式传给对方。当然,到了TCP层,它会把二进制流变成一个的报文段发送给服务器。在发送给每个报文段的时候,都需要对方有一个回应ACK,来保证报文可靠地到达了对方。如果没有回应,那么TCP这一层会进行重新传输,直到可以到达。同一个包有可能被传了好多次,但是HTTP这一层不需要知道这一点,因为是TCP这一层在埋头苦干。
TCP层发送每一个报文的时候,都需要加上自己的地址(即源地址)和它想要去的地方(即目标地址),将这两个信息放到IP头里面,交给IP层进行传输。
IP层需要查看目标地址和自己是否是在同一个局域网。如果是,就发送ARP协议来请求这个目标地址对应的MAC地址,然后将源MAC和目标MAC放入MAC头,发送出去即可。如果不在同一个局域网,就需要发送到网关,还要需要发送ARP协议,来获取网关的MAC地址,然后将源MAC和网关MAC放入MAC头,发送出去。
网关收到包发现MAC符合,取出目标IP地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的MAC地址,将包发给下一跳路由器。这样路由器一跳一跳终于到达目标的局域网。这个时候,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是,在这个局域网上发送ARP,获得这个目标地址的MAC地址,将包发出去。
目标的机器发现MAC地址符合,就将包收起来;发现IP地址符合,根据IP头中协议项,知道自己上一层是TCP协议,于是解析TCP的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个ACK,如果不是就丢弃。
TCP头里面还有端口号,HTTP的服务器正在监听这个端口号。于是,目标机器自然知道是HTTP服务器这个进程想要这个包,于是将包发给HTTP服务器。HTTP服务器的进程看到,原来这个请求是要访问一个网页,于是就把这个网页发给客户端。
05.HTTP返回构建
5.1 构建响应码
- 服务器生成一个响应状态码,用于表示请求的处理结果。
- 常见的状态码包括200表示成功,404表示未找到,500表示服务器内部错误等。
5.2 构建响应头
- 服务器生成一些响应头,包含了一些元数据信息。
- 响应头可以包含内容类型、内容长度、缓存控制、重定向等信息,以便浏览器正确处理响应。
5.3 构建响应体
- 服务器生成响应体,其中包含了实际的响应数据。
- 响应体可以是HTML文档、CSS样式表、JavaScript代码、图像文件等,具体内容取决于服务器的处理结果。
5.4 发送响应数据
发送响应:服务器将生成的HTTP响应发送回浏览器。
- 响应中包含了状态码、响应头和响应体等信息。目前响应内容一般用json来传输数据!
HTTP的返回报文也是有一定格式的。这也是基于HTTP 1.1的。
image
状态码会反应HTTP请求的结果。
- “200”意味着大吉大利;而我们最不想见的,就是“404”,也就是“服务端无法响应这个请求”。然后,短语会大概说一下原因。
接下来是返回首部的key value。
- 这里面,Retry-After表示,告诉客户端应该在多长时间以后再次尝试一下。“503错误”是说“服务暂时不再和这个值配合使用”。
在返回的头部里面也会有Content-Type,表示返回的是HTML,还是JSON。
构造好了返回的HTTP报文,接下来就是把这个报文发送出去。还是交给Socket去发送,还是交给TCP层,让TCP层将返回的HTML,也分成一个个小的段,并且保证每个段都可靠到达。这些段加上TCP头后会交给IP层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。
客户端发现MAC地址符合、IP地址符合,于是就会交给TCP层。根据序列号看是不是自己要的报文段,如果是,则会根据TCP头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。
当浏览器拿到了HTTP的报文。发现返回“200”,一切正常,于是就从正文中将HTML拿出来。HTML是一个标准的网页格式。浏览器只要根据这个格式,展示出一个绚丽多彩的网页。
这就是一个正常的HTTP请求和返回的完整过程。