大前端网络专题篇之HTTP

大前端网络专题篇之HTTP

1️⃣、请简述浏览器输入 URL 地址以后所发生的事情

浏览器解析URL

  • 将url中元素拆分出来

    URL格式,重要的是scheme,host和path

    WX20190731-234236@2x

    按照URL格式拆分:

    WX20190801-012945@2x

    请求需要访问www.lab.glasscom.com域下的dir1目录下的file1.html文件。

    几个例子:

    如果是http://www.lab.glasscom.com/,表示访问根目录下的默认文件(index.html之类的,根据服务器配置信息决定)

    如果是http://www.lab.glasscom.com/index,如果存在index文件就当做文件名处理,如果没有就当做目录名

生成http请求消息

向DNS服务器查询web服务器IP地址

补充:

WX20190801-174811@2x

​ 浏览器不具备将消息发送到网络中的能力,要借助操作系统完成。这时候要知道通信对象的IP地址(不直接使用域名确定通信对象是因为运行效率问题,IP地址长度为32比特,4字节。域名最短几十字节,最多255字节)

​ DNS 中的域名都是用句点来分隔的,比如 www.lab.glasscom.com,这里的句点代表了不同层次之间的界限(相当于公司里面的组织结构不用部、科之类的名称来划分,只是用句点来分隔而已 ),域名中越靠右的层级越高。每个域的信息都存放在相应层级的 DNS 服务器中。

​ 以为 www.lab.glasscom.com 为例,comjp上还有一层域,成为根域。一般书写时候被忽略,明确表示的话是这样www.lab.glasscom.com.

  • DNS 服务器会从域名与 IP 地址的配置文件中(域名与IP对应的映射表)查找相应的记录,并返回 IP 地址。

  • 如果没找到,那么会寻找相应的 DNS 服务器并获取 IP 地址

  • 如果没找到,那么会将查询消息转发到根域DNS服务器

比如查询 www.lab.glasscom.com ,过程如下:

1)先找到最近的DNS服务器(客户端配置的),找到了就返回

2)没有找到的话,就将查询消息转发到根域DNS服务器

3)根域返回了com域的IP,说你去那里问问吧

4)com域返回了glasscom域的IP,说你去问问吧

5)glasscom域返回了lab域的IP ,说你去问问

6)重复上面步骤, 最后找到了,返回IP

WX20190801-232437@2x

创建套接字

创建套接字,套接字实体可以理解为存放通信对象的ip地址,端口号,通信操作的进行状态等的内存空间,协议栈根据套接字中的控制信息工作。看一下套接字内容

WX20191009-233704@2x

本地套接字与服务端套接字连接

也就是三次握手

1)客户端创建一个包含 表示开始数据收发操作的控制信息头部,在这里客户端知道了要连接服务器的哪个套接字,将头部控制位的SYN设置为 1 表示连接,并且设置初始化序号。创建好以后委托IP模块发送

2)IP模块发送后,通过网络传输,服务器上的IP模块将收到的数据传输给TCP模块,服务器根据TCP头部信息找到对应套接字,以后服务器TCP模块返回响应,设置SYN为 1,服务端也会初始化一个序列号,同时设定ACK为客户端初始化序列号加 1,表示确认,以后委托IP模块向客户端返回响应

3)网络包返回到客户端,通过IP模块到TCP模块,这时候向套接字写入服务器IP地址,端口号等,客户端设置ACk为服务端初始化序列号加 1,返回服务器),之后进入随时可以收发数据的阶段

WX20190731-215041@2x

传输数据,数据收发阶段

协议栈一收到数据不会立马发送,与长度优先时间优先有关。而对较大HTTP请求消息数据进行拆分

WX20191009-234123@2x

  • Mtu:最大传输单元

  • Mss:最大分段大小,mtu减去tcp和ip头部

TCP具有确认对方是否收到网络包,并且没收到会进行重新发送的功能,那么是怎么确认的呢?(图中初始化序号为1,但是实际情况一般是随机一个初始序列号。)

WX20191009-234503@2x

TCP模块在拆分数据的时候,计算好每一块相对于从头开始的第几个字节(也就是序号),将字节数加在TCP头部。数据的长度也会告知接收端,不过长度不放在头部(整个网络包长度减去头部长度,就是数据长度)接收方可以通过这样计算数据长度。通过这些信息接收方就能知道数据是否有遗漏。接收方接到后,会把目前接收到的数据长度加起来,算出多少字节,然后把这个数值加 1 后,放在TCP头部的ACK号中返回客户端,表示确认。而发送的包会保存在发送缓冲区内,如果没有收到某些包对应的ACK号,就会重新发送。

  • 滑动窗口:发送一个包,不等待ACK返回,直接发送后续的包,这样能减少等待ACK号的时间浪费。

WX20191010-170402@2x

  • 滑动窗口与接收缓冲区:接收方会告诉发送方自己能接收多少数据,发送方根据这个值对发送数据控制。当接收方收到包以后,会将数据存放在接收缓冲区,并执行接收操作,完成之后释放接收缓冲区的空间,接收方会通过TCP头部告诉发送方自己能接收的数据量

WX20191010-170436@2x

那么在什么时机点返回ACK号和更新窗口的时机,接收方在发送ACK号和滑动窗口更新时,并不会马上把包发送出去,会等待一段时间,这样可以把两种通知合并到一个包里发送(当需要连续发送多个ACK号的时候也可以减少包的数量,在固态发四部分最后一个ACK号就可以了)。

IP与以太网的包收发操作

TCP模块在执行连接、收发、断开各阶段操作的时候,都需要委托IP模块将数据封装成包发送给通信对象。

  • 包的基本结构

WX20191010-184737@2x

  • TCP/IP包

WX20191010-184805@2x

MAC头部与IP头部的作用:

发送方将包的目的地,就是要访问的服务器IP地址写入IP头部中(地址是由TCP模块告知的,TCP在执行链接的时候从应用程序获得的)。IP协议根据这个地址查找包传输方向,从而找到下一个路由器的位置,之后委托以太网协议将包传输过去。这时候,IP协议会查找下一个路由器的以太网地址(MAC地址),并将这个地址写入MAC头部,以太网协议就知道要将包发到哪一个路由器上。

到达路由器后,会查出接下来发往哪个路由器,会查出下一个路由器的MAC地址,并记录到MAC头部中(路由器在收到包的时候MAC头部被舍弃,再次发送的时候加上包含新的MAC地址的新MAC头部)

WX20191011-180136@2x

IP模块将TCP头部和数据块看作一整块二进制数据,收发操作的时候不关心其中内容,也不关心包的丢包与乱序。

IP包转换成电或光信号发送出去,IP生成的网络包只是存放在内存中的数组信息,无法直接发送,需要转换。

  • MAC模块把包取出,给网络包增加3个控制数据,在开头加上报头(用于确认包的读取时机)和起始帧分界符(SFD,用来确认帧的起始位置),在末尾加上用于检测错误的帧校验序列

WX20191012-153336@2x

  • 从包头开始将数字信息按每个比特转成电信号,之后由PHY(MAU)将信号转换为可在网线上传输的格式,并通过网线发送出去

WX20191012-160353@2x

信号在网线和集线器中传输

从计算机发送出来的网络包会通过集线器、路由器、交换机等设备被转发。

WX20191122-171422@2x

请求到达Web服务器,响应返回浏览器

  • 服务器概览

    服务器需要同时和多个客户端通信,一个程序处理多个客户端请求是很难的(需要把握每一个客户端计算机进行通信),因此一般做法的是每一个客户端连接,就启动一个新的服务器程序(也可能是事先启动的),确保服务器程序和客户端是一对一的状态。

WX20191122-211858@2x

  • 服务器接收操作

网卡将接受到的信号(光信号或电信号)转成数字信息,根据包末尾的校验序列来校验错误,如果有错误,接收到的包就是无效的,需要被丢弃。如果包有效就检查MAC头部中的接收方MAC地址,看这个包是不是发给自己的。不是就丢弃。

  • 服务器程序解释请求消息并作出相应

获取HTTP请求消息,服务器程序会根据收到的请求消息中的内容进行相应的处理,并且生成响应消息,将响应消息交给协议栈,协议栈将数据分成多个网络包,然后加上头部发送出去,它们经过交换机和路由器的转发,最终到达客户端。

  • 浏览器接收响应消息

服务器发送的响应消息被分成多个包发送给客户端,客户端接收数据之后把信号还原成数字信息。然后把消息转交给浏览器。

渲染

  • 构建DOM树

  • 构建CSSOM树

  • 构建渲染树

  • 回流

  • 重绘

断开管道并删除套接字

四次挥手:

刚开始双方都处于 establised 状态

1)客户端发送一个数据包,带有 FIN标记,报文中会指定一个序列号,此时客户端属于 FIN_WAIT1状态(FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认)

2)服务器接收到,返回一个数据包带有 ACK标记(客户端的序列号 + 1 的值),此时服务端处于 CLOSE_WAIT状态(CLOSE-WAIT - 等待从本地用户发来的连接中断请求)。

3)服务端也想断开连接,发送数据包,带有 FIN标记,报文中会指定一个序列号,此时服务端处于 LAST_ACK 的状态(LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认)

4)客户端接收到,返回一个数据包带有 ACK标记(服务器的序列号 + 1 的值),此时客户端处于 TIME_WAIT 状态(TIME-WAIT -等待足够的时间以确保远程TCP接收到连接中断请求的确认),一段时间之后进入 CLOSED 状态(CLOSED - 没有任何连接状态;)

WX20190731-224335@2x

之后套接字就没有作用了,会等待一会后删除。

补充

UDP协议与TCP协议区别

TCP会管理发送和确认进度,如果漏掉包,没有收到就会重新发送,收发之前需要建立和断开连接的步骤。

UDP数据很短,一个包就能装下,不用考虑哪个包未收到,重新发送也只是发一个包而已,收到的数据会被当成回复,就不用专门接收确认包。也就是说它没有接收确认,窗口等机制,收发之前也不需要建立和断开连接。只需要从应用程序中取出数据,加上UDP头部,以后交给IP发送就可以了,对于错误与丢包一概不管,但是没有收到回复的时候,应用程序会注意到就会重发。

2️⃣、请列举常见的 HTTP 状态码并介绍它们的含义,至少五个以上。

​ 101 服务器将遵从客户的请求转换到另外一种协议

​ 200 OK 请求被正常处理

​ 301 Moved Permanenlty 永久性重定向

​ 302 Found 临时性重定向

​ 301与302的区别:

​ 访问URI的时候,第一次访问某地址状态码为301,根据Location头部重定向到新的页面,之后再访问这个地址,是直接访问Location头部的地址,不会访问原地址,比如第一次访问 www.qinhanwen.xyz/ 通过Location重定向到www.qinhanwen.xyz/new ,new的地址会被记录到缓存中,之后每次访问都直接访问这个地址,不再访问 www.qinhanwen.xyz/ (在没有清理缓存的情况下)

​ 第一次访问状态码是302时,根据Location重定向。之后访问原地址,也根据Location重定向。就是每次都访问 www.qinhanwen.xyz/ ,在通过Location重定向

​ 304 Not Modified 协商缓存

​ 401 Unauthorized 认证失败

​ 403 Forbidden 访问被拒绝

​ 404 Not Found 无法找到请求的资源

​ 500 Internal Server Error 服务端执行请求错误

​ 503 Services Unavailable 服务器超负荷或者停机维护

3️⃣、请列举常见的 HTTP 头部并介绍它们的作用,至少五个以上。

https://qinhanwen.github.io/2019/02/27/%E5%B8%B8%E8%A7%81http%E5%A4%B4%E9%83%A8/

4️⃣、请列举常用的 HTTP 方法,并介绍 Get 与 Post 请求之间的区别。

常见方法:get 、post、 options、delete、put、 head

区别:

区别 get post
缓存 能被缓存 不能被缓存
安全性 相对post较低,参数直接拼接在url上 在网络节点上捉包,就能完整地获取数据报文
长度限制 对 URL 限制的大多是浏览器和服务器的原因(不同浏览器不一样),本身没有限制 无限制
编码类型 application/x-www-form-url encodedapplication/x-www-form-urlencoded 或 multipart/form-data

GET 和 POST 只是 HTTP 协议中两种请求方式(异曲同工),而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别,只是浏览器厂家根据约定,做得限制而已。

5️⃣、请分别介绍 Cookie 和 Session 的作用及它们之间的区别。

Cookie:

1)客户端与服务端都可以设置cookie,不同域只能看到自己域下的cookie。

2)cookie默认不会跨域,发送请求的时候,机器会查看与域名有关的cookie,如果存在就一起发送到服务器,不存在就不发送。

3)cookie需要跨域的话,AJAX的withCredentials设置为开启,并且服务器设置Access-Control-Allow-Credentials: true。客户端才可以发送cookie,服务端设置cookie才会被客户端接受。

4)跨域的时候传递cookie,Access-Control-Allow-Origin不能是*号。

5)存放在客户端

Session

1)存放在服务器上,由服务端保持状态,但是也需要客户端保存一个标识

2)服务器使用一种类似于散列表的结构来保存信息。

3) 当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id)。

补充:

为什么需要三次握手?

第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。