您当前的位置:首页 > 知乎文章

当我们输入一个url会发生什么?(2)

时间:2022-02-28 10:48:39  知乎原文链接  作者:网盾科技

报文结构

HTTP报文的结构分为请求和响应两种,请求报文封装用户操作产生的动作,告知服务器应采取什么行为,响应报文来告知客户端请求的结果。请求报文格式:

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

响应报文格式:

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

报文的起始行表明了报文的开始,请求和响应各自的起始行的格式也不相同。请求报文的起始行说明要做什么,结构为方法 + 请求URL + 协议版本,中间用空格做分隔:

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

响应报头的起始行说明发生了什么,结构为协议版本 + 状态码 + 描述文本,中间用空格做分隔:

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

方法与状态码

方法来告诉服务端请求报文要做的事情,状态码来通知客户端服务端依据请求报文完成动作之后的大致结果。常见的HTTP方法如下:

class="ztext-empty-paragraph">

1.| 方法 | 含义 | 有无主体 | | ------- | ---------------------------------------------- | -------- | | GET | 从服务端获取资源 | 无 | | HEAD | 只获取资源头部 | 无 | | POST | 向服务端发送数据 | 有 | | PUT | 将客户端发送的数据存到服务端,应用场景多为修改 | 有 | | OPTIONS | 对服务端进行预检,例如服务端支持哪些方法 | 无 | | DELETE | 从服务端删除资源 | 无 |

2. 请求完成时,响应报文中会有一个状态码,用来表示此次请求的状态,是成功了还是失败了,或者时需要重定向。状态码的范围从100到599, 其中有部分是已经定义的。不同的范围表示的含义也不同:

3. | 范围 | 已定义范围 | 含义 | | ------- | ---------------------------------------------- | ---------- | | 100~199 | 100~101 | 信息提示 | | 200~299 | 200~206 | 成功 | | 300~399 | 300~305 | 重定向 | | 400~499 | 400~415 | 客户端错误 | | 500~599 | 500~505 | 服务端错误 |

class="ztext-empty-paragraph">

首部

首部是请求和响应报文中的一些信息,形式为键值对,每对键值结尾是CRLF换行符,它决定了请求或者响应报文的属性,比如Content-Type表明了请求主体的数据类型,Date说明了请求的创建时间。客户端与服务端通过首部来协商具体行为。可以根据请求、响应、结构等,将首部分为五种。

· 请求首部:是放在请求报文中的首部,它被用来告诉服务端一些信息。

· 响应首部:为客户端提供一些可能用到的信息。

· 通用首部:请求与响应报文都包含的首部,例如Date首部

· 实体首部:对于报文实体主体部分的描述,比如Content-Type,表明其数据类型。

· 扩展首部:开发者自己添加的首部字段,用来满足定制化需求。

实体

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

实体部分是可选的,它被用来运送请求或者响应的数据,实体由实体首部 + 实体主体组成,实体首部对实体主体做描述。HTTP/1.1定义了以下的基本实体首部字段:

· Content-Type: 实体主体中的数据类型。

· Content-Length: 实体主体的长度或者大小。

· Content-Language: 和传输的数据最匹配的语言。

· Content-Encoding: 来标识服务端编码时所用的编码方式。

· Content-Location: 要返回的数据的地址。

· Content-Range: 如果是部分实体,用来标记它是实体的哪个部分。

· Content-MD5: 实体主体内容的校验和。

· Last-Modified: 所传输内容在服务器上创建或者最后修改的日期时间。

· Expires: 实体数据试下的日期时间。

· Allow: 所请求资源允许的请求方法。

· ETag: 资源的特定版本的标识符。可以让缓存更高效,并节省带宽。

· Cache-Control: 控制缓存机制的指令。

以上是HTTP报文包含的主要结构,当请求报文到达服务器时,服务器会对报文中的内容解析出来,根据方法、资源路径、首部、和主体来处理请求,然后通过对请求资源的访问结果,来构建响应,回送给客户端。

传输层-TCP

HTTP连接是建立在TCP连接的基础之上的,TCP提供可靠的数据连接。当要传输一个HTTP报文时,报文数据会以流的形式通过一条已经打开的TCP连接按顺序传输,TCP会将收到的数据分成小块,每块是一个TCP分组。

由于数据是分成小块发送的,所以完整可靠的数据传输主要体现在:分组是否完整、分组顺序是否正常、分组是否损坏、分组数据是否重复。这些可以通过TCP的检验和、序列号、确认应答、重发控制、连接管理和窗口机制来控制。

TCP是传输控制协议,传输控制主要依赖首部包含的6个标志,它们控制报文的传输状态,以及发送端和接收端应对数据采取的动作。当它们的值为1时,标志对应的各自功能才允许被执行,比如当URG为1时,报文首部的紧急指针部分才有效。

· URG 紧急指针

· ACK 确认序号有效

· PSH 接收方应该尽快将这个报文段交给应用层。

· RST 重建连接

· SYN 同步序号用来发起一个连接

· FIN 发端完成发送任务

class="ztext-empty-paragraph">

class="ztext-empty-paragraph">

源端口和目的端口:标识发送方和接收方的端口号,一个TCP连接通过4个值确认:源IP、源端口、目的IP、目的端口,其中源IP和目的IP包含在IP分组内。

首部长度:表示TCP首部的字节长度,也能标记出从多少个字节开始,才是需要传输的数据。

TCP段序号:本段报文发送的数据第一个字节的序号,每段报文中的数据的每个字节都有序号,第一个字节的序号从0开始,依次加1,加到2的32次方减1后再次从0开始。

TCP段确认序号:当首部标志ACK为1时,确认序号有效。TCP段被接收端接收后,会回送给发送端一个确认号,为上次接受的最后一个字节序号加1。

检验和:由发送端计算,接收端验证,如果接收方检测到检验和不正确,表明该TCP段可能有损坏,会被丢弃,同时接收端向回送一个重复的确认号(与最近的一次正确的报文传输的确认号重复),表明接收到的TCP段是错误的,并告知自己希望收到的序号。这时发送端需要立即重传出错的TCP段。

紧急指针:当首部标志URG为1时,紧急指针有效,表示发送端向接收端要发送紧急数据。紧急指针是一个正偏移量,它和TCP段序号相加,计算出紧急数据的最后一个字节的序号。比如接收方接收到数据,从序号为1000的字节开始读取,紧急指针为1000,那么紧急数据就是序号从1000到2000之间的字节。这些数据由接收方决定如何处理。

窗口尺寸:决定了TCP一次成块数据流的吞吐量。需要注意的是,它表示的是发送一方的允许对方发送的数据量,比如发送方首部中的窗口大小为1000,就表示发送方最多可以接受对方发来的1000个字节的数据量。这与发送方的数据缓存空间有关,会影响TCP的性能。

首部标志PSH:如果需要告诉接收方将数据立即全部提交给接收进程,发送方需要将PSH置为1,这里的数据是和PSH一起传送的数据以及之前接收到的全部数据。如果接收方收到了PSH为1的标志,需要立即将数据提交给接收进程,不用再等待有没有其他数据进来。

复位标志RST:当RST为1时,表示连接出现了异常情况,接收方将终止连接,通知应用层重新建立连接。

同步序号SYN:用来建立连接,涉及到TCP的三次握手。

1. 开始建立连接时,客户端向服务器发送一个TCP分组,分组首部的SYN为1,并携带一个初始序号,表明这是一个连接请求。

2. 如果服务器接受了连接,会向客户端发送一个TCP分组,分组中会包含SYN和ACK,都为1,同时包含一个确认序号,值为来自客户端的初始序号 + 1,表示连接已经被接受。

3. 客户端收到上一步发来的分组后,会再向服务器发送一段确认报文分组,ACK为1,会再次携带确认序号,值是第二步来自客户端的确认序号+ 1。服务端收到确认信息后,进入已经连接的状态。

在第三步的确认分组中,是可以携带要发送的数据的。

连接终止标志FIN:用来关闭连接,当一端完成数据发送任务后会发送一个FIN标志来终止连接,但因为TCP在两个方向(C-S,S-C)上会有数据传递,每个方向有各自的发送FIN & 确认关闭流程,所以会有四次交互,也称为四次挥手。

1. 如果客户端应用层的数据发送完毕,会导致客户端的TCP报文发送一个FIN,告知服务器准备关闭数据传送。

2. 服务器接收到这个标志后,它发回一个ACK,确认序号为收到的序号加1,同时TCP还要向应用程序发一个文件结束符。

3. 此时服务器关闭这个方向的连接,导致它的TCP也会发送一个FIN。

4. 客户端接收到之后发回一个确认ACK,序号为收到的序号 + 1,连接完全关闭。

TCP段序号与确认序号保证了数据的顺序,检验和确保数据的完整性,紧急指针保证紧急数据可被及时处理。另外,TCP还有一些超时重传、 拥塞避免、慢启动的机制,都可以保证分组数据按照顺序完整的传到目标端。

网络层-IP

如果说TCP分组是包装货物的集装箱,那么IP就是运送集装箱的卡车。IP协议提供了两个节点之间的连接,保证将TCP数据尽可能快地从源端送到终端,但却不能保证传输的可靠性。

IP层会将上层传过来的TCP分组封装,带上自己的首部,再进行选路、是否分片以及重组的工作,最终到达目的地,这个过程中,IP首部起了重要的作用,下面让我们看一下首部的结构。

IP

class="ztext-empty-paragraph">

版本:表示当前IP协议的版本,目前版本号是4,还有一种是6,也就是IPV4和IPV6,如果发送和接收这两端的版本不一致,那么当前IP数据报会被丢弃。

首部长度:整个首部的长度,最长为60字节。

服务类型(TOS):用来区分服务的类型,但其实IP层在工作的时候一直没有实际使用过,现有的TOS只有4bit的子字段,和1bit的未用位。未用位必须置为0。TOS的4个bit中只能将一个置成1,用来表示当前服务类型。4bit对应的4个服务类型分别为:最小时延、最大吞吐量、最高可靠性和最小费用。

路由选择

因为IP首部只包含了目的IP地址,并不体现完整的路径,当向外发送数据时,IP层会根据目的IP在本机路由表中的查询结果来做出选路决策,数据报会逐跳地被运送到目的地,这里的每一跳,就是一次路由选择。

IP层既可配置成路由器,也可以配置成主机。当配置成路由功能时,可以对数据报进行转发,配置成主机时,如果目的IP不是本机IP,数据报会被丢弃。

具有路由功能的IP层在当目标IP不是本机地址的时候是根据什么判断转发到哪一站呢?要理解这个问题,需要先明白路由表的结构,以下是IP层维护的路由表,(windows系统可以在控制台输入netstat -r来查看路由表)

| Destination | Gateway | Flags| Refcnt| Use | Interface| | ------------------ | --------------- | -----|------ |---- | ---------| | 140.252.13.65 | 140.252.13.35 | UGH | 0 | 0 | emd0 | | 127.0.0.1 | 127.0.0.1 | UH | 1 | 0 | lo0 | | default | 140.252.13.33 | UG | 0 | 0 | emd0 | | 140.252.13.32 | 140.252.13.34 | U | 4 |25043| emd0 |

(路由表数据来源于《TCP/IP详解卷一:协议》)

· Destination(目的IP):表示IP数据报最终要到达或者经过的网络地址或者主机地址。

· Gateway(下一跳地址):当前维护路由表设备的相邻路由器的地址

· Flags(标志):表示当前这一条路由记录的属性,具体用五个不同的标志来表示:

U:该路由可以使用

G:如果有这个标志,表示是下一跳是一个网关,如果没有,表示下一跳是和当前设备在一个网段,也就是可以直接把数据报发过去

H: 下一跳是一个主机还是一个网络,有这个标志,表示主机,没有,则表示下一跳的路由是一个网络

D:该路由是由重定向报文创建的

M:该路由已被重定向报文修改

Interface:当前路由项的物理端口

每收到一个数据报时候,IP层就会根据目的IP在路由表里查询,根据查询状态会导向三种结果:

1. 找到了与目的IP完全匹配的路由项,将报文发给该路由项的下一站路由(Gateway)或者网络接口(Interface)

2.找到了与目的IP的网络号匹配的路由项,将报文发给该路由项的下一站路由(Gateway)或者网络接口(Interface)

3. 前两者都没有找到,就看路由表里有没有默认路由项(default),有的话发给它指定的下一站路由(Gateway)

要是上边三个都没有结果,那么数据报就不能被发送。IP数据报就是这样一跳一跳地被送往目的主机的,但数据报有固有的长度,一旦超出了目的主机的MTU,就会被分片。

最后

一个网络请求从源端一层层封装,再到终端一层层拆分,最后的所有过程基本梳理清楚,文章只是简单梳理了一下大概流程,并且只以HTTP报文通过TCP协议经过IP传送这一过程为例,实际还有很多概念没有覆盖,比如链路层的尾部封装、 IP的动态选路、逆地址解析协议RARP、UDP协议相关的概念,建议大家可以阅读下面列出的参考资料,相信会有更多收获。

上一篇      下一篇    删除文章    编辑文章
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
推荐资讯
相关文章
    无相关信息
栏目更新
栏目热门