1.1 TCP/IP 五层(四层)模型

(由下而上)

  1. 物理层
  2. 数据链路层
  3. 网络层
  4. 传输层
  5. 应用层(TCP/IP 五层模型与 OSI 七层模型的区别就在这里,后者是会话层、表示层、应用层)

1.2 主机、路由器、交换机

  • 主机,涉及到物理层到应用层(通过应用程序满足网络通信要求)
  • 路由器,涉及到物理层到网络层(组建局域网,进行网络数据包转发)
  • 交换机,涉及到物理层到数据链路层(对路由器的接口进行扩展,不需要考虑组网的问题)

1.3 网络通信的基本流程

  1. 应用程序接受用户输入,构建出结构化的数据包。以什么样的方式构建,有应用程序自己确定。在网络中,传输的数据要么是字符串,要么是二进制 bit 流。如何把结构化的数据,转换为字符串/二进制 bit 流,就是序列化;反过来,就是反序列化
  2. 应用层调用传输层的 API 接口,在应用层结构化数据包上加上传输层协议的报头
  3. 接下来传输层调用网络层 API 接口,以常用的 IP 协议为例,在上一层的报文添上 IP 报头,包含源 IP 、目的 IP 等
  4. 往下传递到数据链路层,这次不仅添加报头,还添加报文尾部的校验和。这一层常用的协议有以太网,以太网数据帧,就是由以太网报头 + 有效载荷 + 帧尾组成;如果是无线网的话使用的是协议是 802.11,和以太网是并列关系,数据格式不一样,功能略有差别
  5. 以太网继续把这样的数据帧交给硬件设备,也就是物理层。一直到现在,数据才真正走出计算机,由 光信号/电信号/电磁波信号 传递出去

这样就是封装的过程。在网络上传递的就是这种“包裹”起来的报文。网络传输中的设备,根据自己需要获取报头或报尾中的内容就叫做分用。

对应看到上面提到的交换机、路由器、主机

  • 交换机工作在数据链路层,在接受到报文后,会分用以太网数据帧的报头(报头中的内容就足以支持交换机完成下一步工作),并不会分用网络层报文,接下来重新构建以太网数据帧封装报文
  • 路由器工作在网络层。在接收到报文后,会分用数据链路层报文、网络层报文,并不会分用传输层报文,获得网络层报文中的信息后,就可以根据需要重新构建网络数据报,封装报文
  • 主机在接受到报文后,按照上面五点的顺序,反过来分用直到得到应用层的结构化数据。对应的应用程序不只由程序员定义了序列化规则、结构化规则,也有对应的反序列化、数据取用规则,在应用程序中便可以使用,就完成了网络传输

所谓“协议”,其实就是一种服务器、客户端之间达成的对于数据的约定

1.4 TCP 和 UDP

1.4.1 特点
  1. TCP 面向字节流,UDP 面向数据报。所谓字节流,就是以字节为单位,而我们的数据报就是一次发送的一整个报文,要么全接受,要么全丢失
  2. TCP 有连接,UDP 无连接。这里的连接,是抽象的概念,简单来说就是对端的信息,如 IP、端口等;或者更进一步,其对应内核中的数据结构(比如在 Linux 系统中,TCP 就有一个全连接队列,是通过 C 语言版本的多态实现的)
  3. TCP 可靠,UDP 不可靠。可靠是指的 TCP 会通过保存的连接,在超时重连、滑动窗口等机制的作用下,重新发送丢失的报文;而 UDP 相对更加简单,只是发送,是否丢失不管
  4. 两者都是全双工
1.4.2 UDP
源端口 | 目的端口 | 长度 | 校验和 | 载荷

UDP 作为传输层协议,考虑的部分到端口。整体来说,由 UDP 报头和应用层数据正文组成。其中,报头由源端口、目的端口、长度和校验和组成,每个部分分配了2个字节。其中,长度指的是整个UDP 报文(包括 UDP 报头和应用层正文)。因为长度最大只允许到65535,所以UDP 但个报文的最大长度是64kb

1.4.3 TCP
16 位源端口号 | 16 位目的端口号
          32 位序号
         32 位确认序号
4位首部长度|6位保留|6位标志位|16位窗口大小|
    16位校验和  |   16位紧急指针
              选项
              数据
  • 六位保留,是吸收了 UDP 在使用之后,很多结构已经跟不上时代需求的问题,留下的。如果有需要,就可以使用这6位保留去保存其他内容

  • 6位标志位,分别包含:URG, ACK, PSH, RST, SYN, FIN

    • URG,紧急指针位,在设置时,16位紧急指针字段生效,读取时直接从其指向的位置读取
    • ACK,应答位,当设置时,16位应答序号生效
    • PSH,催促标志位,让接收方尽快把数据从接收缓冲区 read 到上层处理
    • RST,重置标志位,设置时表示发送标志位的一方已经认为连接失效,立刻断开连接,不再执行正常的四次挥手过程,直接释放端口资源
    • SYN,同步标志位,携带的一方表示请求建立连接
    • FIN,结束位,发送的一方请求断开连接
  • 4位首部长度,单位是 4 个字节,表示 TCP 报文首部长度,因为选项是可选项,长度不固定,所以需要约束读取长度

1.4.3.1 确认应答

在 TCP 报头中,有两个内容,分别是 32 位序号和 32 位确认序号。32 位序号表示了当前发送的内容第一个字节的序号(虽然 TCP 不像 UDP 那样有结构造成的上限,理论是可以有无限长的正文,但是传输时不允许,后面会提到);32 位确认序号是接收方在接收到报文后,根据其中的 32 位序号,确定 32 位确认序号(以连续接收到的最大字节序号 + 1),并将 6 位标志位中 ACK 的对应位置设置,表示 32 位确认序号有效。同时,这里的确认序号还有一个规则,那就是只认连续接收报文的最小值。比如第一次发送 0 ~ 1000,第二次发送 1001 ~ 2000,第三次 2001 ~ 3000,其中一三次到达,二次丢失,那么接收方的 32 位确认序号只会被设置为 1001

确认应答机制除了“确认”的作用,还可以起到排序的作用。实际传输中,即使是先发的报文也不一定能保证先到达接收方接收缓冲区。接收方便可以根据 32 位序号,把接收缓冲区中的若干报文进行排序,将顺序的数据交付上层使用

1.4.3.2 超时重传

超时重传由定时器确认,当发送某条报文后,如果在规定时间内没有接收到 ACK 应答报文,就认为该报文丢失重发;定时器仍然会生效,但是等待的时间更长,以此类推。如果等待了几次都没有效果,就会发送“心跳包”给对端(不携带业务数据),如果仍然没有应答,就会发送一个含有 RST 的请求,表示重置连接

TCP 可靠性的实现,主要就是依靠确认应答和超时重传机制

1.4.3.3 三次握手四次挥手

建立连接的过程——三次握手,其实就是一个投石问路,摸清双向连通性以及双方收发能力是否正常

  • 第一次握手:客户端发送携带设置了 SYN 的请求,随之进入 SYN_SEND 状态;服务端接收到后,从 LISTEN 状态进入 SYN_RECV 状态
  • 第二次握手:这一次其实等价于两次。一是设置了 ACK,表示客户端到服务器没问题;另一个设置 SYN,表示去测试服务端到客户端的连通性。
  • 第三次握手:客户端接收到第二次握手的报文后,进入 ESTABLISHED,发送最后一次 ACK;服务器接收到这一次报文,也进入 ESTABLISHED,完成三次握手的过程

除了这种为了连通性进行的内容,还可以在三次握手的过程中,明确一些关键信息,比如确认初始序号,考虑以下情况:第一次建立的连接因为网络问题断开,建立第二次连接后,第一次连接在网络中迷失的报文到达了,那么这份报文就不应该被处理。所以确认序号如果相差甚远,就认为这份报文无效

三次握手,只能由客户端发起


断开连接的过程——四次挥手,一般是由客户端断开连接,但是也可以有服务器断开

请求断开的一方发送携带 FIN 标志位的请求,被断开方接收到后,由操作系统内核立即返回 ACK 应答,此时被断开方进入 CLOSE_WAIT 状态。当被断开方完成剩余工作逻辑处理,就会返回含有 FIN 标志位的请求给请求断开的一方,并且进入 LAST_ACK 状态。请求断开的一方接收到后进入 TIME_WAIT 状态,并且发送最后一次 ACK。当被断开方接收到最后一次 ACK 之后,一般是由客户端断开连接

TIME_WAIT 等待的时间是两个 MSL(Maximum Segment Lifetime)。一个 MSL 是一个 TCP 报文在传输流程中存活的最长时间,等待两个 MSL 有两个目的:

  1. 如果 ACK 丢失,那么被断开方还能重发 FIN。
  2. 让还在传输的老报文要么到达要么过期,不要影响下一个进程
1.4.3.4 滑动窗口

“窗口”指的其实就是我们要发送的数据的一部分,将这部分数据分成若干部分,各个部分一起分开同时传输;“滑动”指的就是当前面的数据完成传输后,就可以把“窗口”向后移动,把后面的数据也拉进窗口中进行传输。这里的窗口越大,网络的吞吐量越大,我们传输的速度也就越快(但不是无限制的,后面的流量控制、拥塞控制都做出了限制)。

前面提到过,在 ACK 报文中 32 位确认序号是有效的;滑动窗口的“滑动”就使用 ACK 进行判定:比如说当前滑动窗口分为 1~1000、1001~2000、2001~3000 三个部分传输,当接收到含有 1001 的 ACK 报文后,就把滑动窗口,把 3000~3001也开始传输

1.4.3.5 快重传

前面提到的超时重传往往在网络环境非常不好,所有报文都丢失的情况下被触发。但是相对更常见的是因为短暂的网络波动导致的部分报文丢失,快重传就是为了快速的解决这种情况下的报文丢失问题。

在滑动窗口中,我们提到过 32 位确认序号,并且也提到过 32 位确认序号是已经接收到的连续区间的下一个位置,所以如果我们连续接收到这个位置的 ACK 报文,就意味着这个位置的报文丢失了。

快重传做的就是,只要连续三次接收到这个位置冗余的 ACK 报文,就认为他已经丢失,开始重新传输

1.4.3.6 流量控制

滑动窗口越大,网络吞吐量越大,但是无论是网络传输能力还是对端接收能力都是限制。流量控制就是为了迎合对方的接收能力。

在三次握手的过程中,接收端会在 16 位窗口大小中根据自己的接收能力确认一个初始的窗口大小。三次握手完成后,就会先用这个大小作为滑动窗口的大小发送。在后续传输过程中,接收端会在 ACK 报文中动态设置窗口大小,发送端也会不断的相应调整。

当接收端缓冲区完全被打满不能继续接收时,就会将窗口大小设置为零,这是发送端便会停止发送。但是不会一直等下去,而是一段时间就发送一个试探报文(不含要传输的数据)去确认新的窗口大小,如果得到非零大小,就继续以这个大小为滑动窗口大小传输

虽然上面说的是 16 位窗口大小,但是这并不是和UDP一样最大只有64kb。在选项字段中有一个窗口扩展倍数,以 2 为指数增长,在三次握手的过程中互相确定自身的缩放倍数。如果双方在一、二次握手中都有设置选项中的缩放字段,后续就都是用这个缩放倍数,并且不可更改

1.4.3.7 拥塞控制

拥塞控制是在网络环境层面对滑动窗口的大小做出了限制,不过这里确认的窗口叫做拥塞窗口,实际滑动窗口的大小是拥塞窗口大小和 16 位窗口大小的较小值。

初始情况下,拥塞窗口的大小是 1 MSS,开始乘法增大(二的指数增长),这个阶段叫做慢启动;到达慢启动阈值后,转换为线性增长(每次 + 1),这个阶段叫做拥塞避免。接下来有可能会出现两种情况:

  1. 快重传。这种情况下,我们不认为是网络到达传输能力上限,因此我们以当前拥塞窗口为基准,取一半的大小作为慢启动的新阈值,并开始慢启动后的拥塞避免(线性增长),这个过程叫做快恢复
  2. 超时重传。此时,我们认为网络环境很差了,所以我们会从最初的起点 1 MSS 开始重新探测,执行之前的慢启动过程

MSS,指的是 Maximum Segment Size,是单个 TCP 报文能够承载的应用数据最大值,即 MTU - IP 头部最小长度 - TCP 头部最小长度,在一二次握手的过程中,由双方在选项中携带的 MSS 的较小值确定。

1.4.3.8 延迟应答

在上面流量管理的机制下,我们不难得出一个结论:16位窗口大小的值越大,就越有可能获得更大的传输效率。流量管理其实主要是因为缓冲区可能会被上层还没有处理的数据打满,因此如果接收端等待一会儿再应答的话,应用程序可能就把数据取走了,接收端也就能返回更大的窗口大小。

但是并不意味着接收端能一直等下去,因为发送端还有超时重传和快重传机制,所以当接收到几次或者经过一定时间后,接收端就必须返回

1.4.3.9 捎带应答

捎带应答指的是发送数据报文时,顺手发送 ACK 应答。(第二次握手可以认为思路上相似,但是不是捎带应答)

1.4.3.10 面向字节流

TCP 面向字节流的特点支持了滑动窗口、确认应答等机制,但是带来了另一个问题:粘包,即分不开应用层数据和其他报文内容。解决方法大致分为两种

  • 使用分隔符做出标记,比如 \r\n
  • 记录正文长度,只读取这些长度的内容

1.5 传输层数据组织格式

1.5.1 XML
<response>
  <school>
    <name>复日大学</name>
    <location>上海</location>
  </school>
</response>

可读性好,冗余多

1.5.2 json
{
  "school": "复日大学",  
  "position": "上海"
}

可读性一般,冗余中等,使用最多的数据组织格式

1.5.3 protobuf

二进制,占用带宽最少,用开发效率换取执行效率

1.6 IP 协议

1.6.1 报文结构
4位版本|4位首部长度|8位服务类型|16位总长度
      16位标识|3位标志|13位片偏移
    8位生存时间|8位协议|16位首部校验和
              32位源IP地址
            32位目的IP地址
                选项
                数据
  • 4位版本,包括两种,一种是IPV4,另一种是IPV6,中国是世界上支持IPV6最好的国家,没有之一。IPV4现在面临的最大问题是 IP 地址不足,虽然有随机分配、公私网ip等方法治标式的解决,但是不如IPV6治本的解决。IPV4通过4字节来存储IP地址,但是IPV6通过16个字节,这个大小使得即使给地球上的每一粒沙子分配一个 IPV6 地址都是绰绰有余的
  • 4位首部长度,和 TCP 一样,以4个字节为单位
  • 16位总长度,虽然和 UDP 一样,有结构约束的空间上限,但是 IP 报头支持分片组装,所以不必担心长度不够问题
  • 16位标识、3位标志、13位片偏移,是支持IP报头分片组装的核心结构。16位标识是对数据包的标识,相同的标识表示这些包都属于同一个IP报文;3位标志中,有一位代表是否开启了分片,另外一位标识当前分片是否是最后一个分片;13位片偏移则表示了当前分片在整个ip报文中所处的偏移量,用来组装出一整个完整报文
  • 8位生存时间ttl,代表一个报文最多可以被路由器转发多少次,如果在这些次数内还没有到达,就会认为无法访问,比如大多数国内网站(比如 www.baidu.com www.bilibili.com)就比国外网站(www.bing.com www.github.com)需要更少的路由器转发次数
1.6.2 IPV4 的问题

IPV4 面临的最大的问题,就是在现在这个时代能连接网络的设备太多,不止手机电脑,家里的冰箱洗衣机现在都可能能连接网络。所以为了解决这个问题,从 IPV4 本身出发,主要有两种方式:

  1. 随机分配
    虽然说上网的设备很多,但是不是所有设备都在同一时间上网,但是这种方法既不可靠又复杂。
  2. 公网/私网IP
    首先我们规定以下特征的 ip 地址都是私网 ip
  • 10.*.*.*
  • 172.16.*.* ~ 172.31.*.*
  • 192.168.*.*

然后,规定:私网 ip 不能直接在公网上路由,即不能直接访问互联网。这样,在私网中,ip 是不能重复的,但是放眼到整个互联网中,是可以存在无数个持有相同私网ip的计算机的,这样ip地址不足的问题就得到极大缓解了

那么私网ip怎样到公网访问呢?NAT 网络地址转换解决的就是这个问题。路由器在拿到私网ip中对某个目的ip的访问请求后(大多数情况由路由器完成),会将私网ip替换为能在互联网上访问的公网ip,这样请求就能够在互联网上传递,直到到达服务器。服务器接收到请求处理后返回应答时,也会使用相同的流程发送,最终到达出发时的路由器。那路由器这时又怎样知道把这个应答交给谁呢?

在进行 NAT 时,用类似哈希表的结构完成 端口-私网ip 的映射,这样虽然服务器返回应答中包含的目的ip是路由器的公网ip,但是端口还是进行 NAT 时使用的端口,这样就可以获得私网 IP 了

1.6.3 网络号、主机号

IP 地址分为两部分,一个是网络号,一个是主机号。一个网络号标识了一个网段,主机号则表示了其中一个主机。路由器只能带自己网段的机器上网,但是如果手动配置并且配置错了网段,主机即使连接上了路由器也无法上网

1.6.4 子网掩码

网络号和主机号的占比实际上不是固定的,使用子网掩码和 IP 进行按位与。子网掩码左半部分都是1,右半部分是0,按位与得到的就是网络号

(还有就是学校里会考的上古时期的 ABCDE 类 IP)

特殊的几类主机号

  1. 主机号为0,代表一个网段中的所有机器,或者说代表一个网段
  2. 主机号为全1,代表广播地址,向一个网段中的所有机器广播,比如寻找投屏设备,会像所有设备发送询问请求(UDP)
  3. 127.0.0.1,本地环回

1.7 MAC

MAC 地址理论上唯一标识了一个网卡,六个字节够用。由于 MTU(Maximum Transform Unit)限制,MAC 地址载荷部分如果是携带 IP 报文的话,那么载荷最大是 1500 字节

1.7 HTTP 协议

1.7.1 基本结构

HTTP是纯文本结构的协议,基本结构是 首行(方法、URL、HTTP版本) - 请求头 - 正文。

1.7.1.1 URL

描述网络上唯一资源的位置(不是 HTTP 中的概念,在各种协议中都可以使用),以我喜欢的一个 Youtube 博主 diinki 的视频链接为例

https://www.youtube.com/watch?v=H7RQYREJO98&t=94s
  • https://,这一部分表明了是哪种协议。如果这里是 https 协议,那么就会自动匹配到服务器的 443 端口,如果是 http 协议,就会自动匹配到服务器的 80 端口。协议字段省略的话,默认是 http 协议
  • www.youtube.com/,这一部分指明域名/服务器IP。域名和服务器 IP 是可以相互转化的,IP 地址是一个点分十进制数字,很难记住,但是通过 DNS 这一应用层协议可以完成转化,从而明确固定到唯一的服务器。这里还可以在域名后通过类似 127.0.0.1:8080 的方式制定端口。端口号有固定了服务器上唯一的一个进程,即明确了服务器是那个程序处理请求

DNS 服务器负责完成域名到实际IP地址的转换工作,全世界一共有 11 台 DNS 根服务器,大部分都在米国。主机也不会每次访问网站都请求 DNS 提供 IP 而是请求到一次后做出缓存

  • watch,是带层级的目录结构,这里的层级结构就是在 Web 根目录下搭建起来的
  • ? 后,指明的是查询字符串,即对请求的更进一步描述,通过键值对的方式构成,规定键和值之间用 = 隔开,键值对之间用& 隔开
  • 查询字符串后面,可能会有类似于 #xxxx 的片段表示,用来精确表示到页面中的某个部件

其实整个 URL 就是明确:我要访问哪个、怎样访问那个资源,比如以到旦苑吃饭为例,用 URL 可以表示为

复旦大学://旦苑食堂:18/炒菜/辣子鸡丁?辣度=重辣&带米饭=带

这就表示,我要到复旦大学旦苑餐厅的18号窗口,在炒菜里选了辣子鸡丁,要求重辣而且带米饭

URL encode

https://cn.bing.com/search?pglt=161&q=C%2B%2B&cvid=4d6344edf42e42c08caa80880e5b9475&gs_lcrp=EgRlZGdlKgYIABBFGDkyBggAEEUYOTIGCAEQABhAMgYIAhAAGEAyBggDEAAYQDIGCAQQABhAMgYIBRAAGEAyBggGEEUYQTIGCAcQRRhBMgYICBBFGEHSAQg0NDIzajBqN6gCALACAA&FORM=ANSPA1&PC=CNNDDB&source=chrome.ob

URL 中,很多符号是不能直接在查询字符串中作为信息传递的,比如上面提到的 & ? 等,以及很多中文、非英语文字也不能直接传递

所以我们使用 URL encode 的方式,将这些内容转移之后进行传输,规则是:将需要转移的字符转换为 16 进制,然后四位一个十六进制数字表示,每个字节由 % 隔开,例如 C++ 转移之后就是 C%2B%2B

但是浏览器展示的时候,可能会展示转义之前的结果。

1.7.1.2 GET 方法和 POST 方法的区别
  1. GET 方法和 POST 方法没有本质上的区别,很多情况下可以混着用,但是区别主要体现在两个方面,一个是语义上的区别,另一个是携带数据的方式

  2. 从语义上来说,GET 方法用来获取数据,POST 方法用来上传数据

  3. 从携带数据的方式上,GET 把获取数据的请求放在 URL 中,POST 把数据放在 body 正文里面

  4. 但是实际上两者可以混着用的原因,在于:

    • HTTP 没有规定 GET 不能携带 body 正文,只不过可能一些浏览器/客户端没有支持
    • HTTP 建议 GET 方法设计为幂等的(实际上已经很少了,因为类似于个性化推荐的需求),对于 POST 无要求。因此如果把 GET 方法设计成幂等的,可以进行缓存

1. POST 方法比 GET 方法更安全?
其实不一定,考虑在登陆场景下,对于 GET 方法而言,确实会直接把用户名密码等放进请求字符串中,但是 POST 方法也是放在 body 里,只是不直接在浏览器上方地址栏显示。

这里的不安全,不在于放在哪里,在于只要明文传输,就是不安全的。POST 放在正文,最简单的方式就是通过类似 Fiddler 这样的抓包工具,就可以直接获取用户名和密码

2. URL 有长度限制?
在远古时代(Windows XP),那时的 IE 浏览器等确实会有 URL 长度限制,但是现在大部分浏览器已经没有了,而且我们还是经常能够看到很长很长的 URL 的,并且 HTTP 本身并没有做出这样的规定

3. GET 不能传递二进制数据?
首先从正文上讲,GET 并非禁止携带 body,所以可以把二进制数据放在正文里;其次,从 URL 上来说,虽然它是纯文本的,但是可以通过 Base64 将二进制数据转化为文本放在 URL 里传输

1.7.1.3 请求头

请求头在首行之后,由若干个规定好的键值对组成,其中常见的有如下几个

Content-Length

用来标记正文长度。前面在说报文结构的时候就提到过,请求头和正文之间有空行。对于没有携带 body 的 HTTP 请求来说,直接读取到空行就是读完了请求;但是对于携带 body 的请求,读取到了空行,如果没有 Content-Length 这样指定长度的字段,那么就无法完整的读取出请求正文。Content-Length 表明的就是正文的长度

Content-Type

用来指示正文的数据格式,即告知接收方应该通过怎样的方式处理这些数据。常用的类型有如下几种

HTML,text/html,浏览器解析标签,把标签转换为界面显示,因为 html 可能涉及中文等非英文字符,所以往往会加上 charset 表明编码方式

  • CSS, text/css,浏览器解析选择器和属性,并把内容应用到指定的页面上
  • JS,application/javascript,浏览器通过 js 引擎解析执行 js 中的逻辑
  • JSON,application/json,浏览器不进行处理,由程序员写的程序进行读取操作
  • IMAGE,image/pngimage/jpg,浏览器解析图片的二进制数据后在页面上进行显示

User-Agent

现在这一点可能并不明显,在十几年前互网刚刚兴起的时候,浏览器支持的功能是具有区别的。因此会出现有的浏览器支持某种功能但是其他浏览器不支持的情况。所以,为了区分返回内容,就有了 User-Agent

User-Agent 指明了用户使用的浏览器以及操作系统情况,方便服务器相应返回匹配的内容

Referer

用来指明当前请求是从哪个页面跳转而来(如果是从浏览器顶部收藏夹或者直接输入 URL 访问的方式不算)

Cookie

浏览器为了保护操作系统,是禁止 JS 对磁盘文件进行访问的,但是有些情况下,有希望能够把数据保存到用户磁盘上,这时就引入了 Cookie 的机制。

关于Cookie 机制更详细的内容,可以参考这篇博客,这里不再赘述了

https://blog.csdn.net/wangjialelele/article/details/161166030?spm=1001.2014.3001.5501

1.7.2 状态码

提供状态码,就是为了快速找到问题所在

2xx,都是成功,不过成功类型不一样

3xx,都是重定向:301 Move permanently;302 Move temporarily,临时重定向,比如更换域名时,访问老域名就可以重定向到新域名

4xx,请求构造有问题:403 Forbidden,访问者无权限;404 Page Not Found,访问的页面不存在;405 Method Not Allowed,请求的方法不存在,比如使用服务器没有实现的方法

5xx,服务器的问题:500 Internal Server Error,服务器内部错误;504 Gateway Timeout,当服务器内部压力过大时,来不及处理客户端请求就会返回504;502 Bad Gateway,比如服务器挂了几个,网关认为不再有能力提供服务,就会返回502

1.8 HTTPS

1.8.1 “S” 是指什么?

S 指的是 Secure,使用 SSL/TLS 等应用层协议

1.8.2 对称加密和非对称加密

对称加密,使用同一把密钥进行加密解密;非对称加密,使用两把密钥,一把是公钥,一把是私钥,规定一把加密一把解密。

对称加密相比非对称加密加解密效率更高,安全性低。但是无论是对称加密,还是非对称加密,单独还是直接结合起来使用都无法抵御中间人攻击。

1.8.3 引入 CA 机构

因此我们引入可信任的第三方:CA 机构。首先我们给 CA 机构提出申请,通过的话,CA 机构会给我们一份证书,其中包括证书认证机构、证书有效期、服务器域名、服务器公钥等信息;同时 CA 机构对这些内容形成数字摘要,对这份数字摘要用 CA 机构自己持有的私钥进行加密,最后将加密过的数字摘要和前面的信息拼接在一起,形成数字证书交给服务器。

当有客户端申请连接时,服务器就把这份数字证书发给客户端。客户端操作系统中会内置知名 CA 机构的公钥,使用这个公钥解密被加密的数字摘要,同时对证书的明文部分同样方法生成数字摘要,如果两份摘要相同,就认为证书中的服务器公钥等信息是没问题的。

接下来客户端生成一份对称加密密钥,使用获得的服务器公钥加密,发送给服务器,后续客户端-服务器就使用对称加密的方式进行数据传输

更加详细的内容,查看 https://blog.csdn.net/wangjialelele/article/details/154278660?spm=1001.2014.3001.5501

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐