收集于互联网,侵删

计网八股文

OSI 参考模型

OSI 从上到下分为 7 层:

应用层:应用层协议定义的是应用进程间的通信和交互的规则,不同的网络应用需要不同的应用层协议
表示层:把数据转换为能与接收者的系统格式兼容并适合传输的格式
会话层:在数据传输中设置和维护电脑网络中两台电脑之间的通信连接
传输层:向两台主机进程之间的通信提供通用的数据传输服务
网络层:基于网络层地址(IP地址)进行不同网络系统间的路径选择
数据链路层:在不可靠的物理介质上提供可靠的传输
物理层:在局域网上透明地传送比特,尽可能屏蔽掉具体传输介质和物理设备的差异

TCP/IP 参考模型

从上到下分为 4 层,对应于 OSI 中的 5 层:

  1. 应用层:对应于 OSI 参考模型的应用层,为用户提供所需要的各种服务。定义的是应用进程间的通信和交互的规则,不同的网络应用需要不同的应用层协议。协议包括 SMTP、HTTP、FTP 等
  2. 传输层:对应于 OSI 参考模型的传输层,为应用层实体提供端到端的、通用的通信功能,保证了数据包的顺序传送及数据的完整性。“通用的”是指不同的应用可以使用同一个运输层服务。协议包括 TCP、UDP 等
  3. 网络层(或网际互联层):对应于 OSI 参考模型的网络层,主要解决主机到主机的路由问题。协议包括 IP、ICMP 等
  4. 网络接入层:对应于 OSI 参考模型的物理层和数据链路层,负责相邻的物理节点间的可靠数据传输。协议包括 ARP、IEEE 802.2 等

TCP/IP 参考模型各层常见协议

protocol

![5cKLtR](/Users/qlzhou/Desktop/TCP 参考模型各层协议.png)

将“网络接入层”进一步分为“数据链路层”与“物理层”,得到五层协议模型。各层的常见协议如下:

TCP/IP 协议层 协议 作用
应用层 HTTP 超文本传输协议(HyperText Transfer Protocol)
FTP 文件传输协议(File Transfer Protocol)用于在客户端和服务器之间进行文件传输
SMTP 文件传输协议(File Transfer Protocol)用于在客户端和服务器之间进行文件传输
TELNET Telnet 是服务器远程登录控制的标准协议与主要方式
DNS 域名系统(Domain Name System)是域名和 IP 地址相互映射的分布式数据库
SSH 安全外壳协议(Secure Shell)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境
DHCP 动态主机配置协议(Dynamic Host Configuration Protocol)的主要作用是集中管理、动态分配 IP 地址,提升地址的使用率
传输层 TCP 传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议
UDP 用户数据报协议(User Datagram Protocol)是一个简单的、无连接的、不可靠的、面向数据报的通信协议
网络层 IP 网际协议(Internet Protocol)是用于分组交换数据网络的一种协议,功能包括寻址、路由、尽最大努力交付数据包
ICMP 互联网控制消息协议(Internet Control Message Protocol)用于返回通信环境的错误消息。traceroute 和 ping 都是基于 ICMP 消息实现的,traceroute 是通过发送含有特殊 TTL 的包,然后接收 ICMP 超时消息和目标不可达消息来实现的;ping 则是用 ICMP 的“Echo request (8)”和“Echo reply (0)”消息来实现的
IGMP 因特网组管理协议(Internet Group Management Protocol )管理 IP 协议多播组成员
RIP 路由信息协议(Routing Information Protocol)是一种内部网关协议(IGP),是距离向量路由协议的一种实现
OSFP 开放式最短路径优先(Open Shortest Path First)是一种内部网关协议(IGP),使用 Dijkstra 算法计算最短路径,是链路状态路由协议的一种实现
BGP 边界网关协议(Border Gateway Protocol)是互联网上一个核心的去中心化自治路由协议,属于矢量路由协议。BGP 用于互联网上,将自治系统视作一个整体;每个自治系统使用 IGP(代表实现有 RIP 和 OSPF)进行路由
数据链路层 ARP* 地址解析协议(Address Resolution Protocol)通过 IP 寻找 MAC 地址
ARQ 自动重传请求(Automatic Repeat-reQuest)是一种错误纠正协议
物理层 IEEE802 IEEE 802 指 IEEE 标准中关于局域网和城域网的一系列标准,其中最广泛使用的有以太网、令牌环、无线局域网等
  • ARP 协议:ARP 协议应该属于哪一层?一种说法是属于网络层,因为 IP 协议使用 ARP 协议;另一种说法是属于数据链路层,因为 MAC 地址是数据链路层的内容。在 OSI 模型中,ARP 协议属于链路层;而在 TCP/IP 模型中,ARP 协议属于网络层。

集线器、网桥、交换机、路由器

  1. 网线是物理层的硬件
  2. 集线器(Hub)是物理层的硬件,连接所有的线路,广播所有信息
  3. 网桥(Bridge)是数据链路层的硬件。网桥隔离两个端口,不同的端口形成单独的冲突域,减少网内冲突。网桥在不同或相同类型的 LAN 之间存储并转发数据帧,根据 MAC 头部来决定转发端口,显然是数据链路层的设备
  4. 交换机(Switch)是数据链路层的硬件,相当于多端口的网桥。交换机内部存储 MAC 表,只会将数据帧发送到指定的目的地址
  5. 路由器(Router)是网络层的硬件,根据 IP 地址进行寻址,不同子网间的数据传输隔离

比特、帧、数据包、数据段、报文

PDU:Prtocol data unit,协议数据单元,指对等层协议之间交换的信息单元。PDU 再往上就是数据(data)。

在 OSI 模型里,PDU 和底下四层相关:

  1. 物理层———比特(Bit)
  2. 数据链路层———帧(Frame)
  3. 网络层———分组、数据包(Packet)
  4. 传输层———数据段(Segment)

第五层或以上为数据(data)。也有一种说法是,应用层的信息称为消息、报文(message),表示完整的信息。

MSL、TTL、RTT 是什么?

MSL(Maximum segment lifetime):报文最大生存时间。它是任何 TCP 报文在网络上存在的最长时间,超过这个时间报文将被丢弃。实际应用中常用的设置是 30 秒,1 分钟和 2 分钟。

  1. 应用场景:TCP 四次挥手时,需要在 TIME-WAIT 状态等待 2MSL 的时间,可以保证本次连接产生的所有报文段都从网络中消失。

TTL(Time to live):IP 数据报在网络中可以存活的总跳数,称为“生存时间”,但并不是一个真正的时间。该域由源主机设置初始值,每经过一个路由器,跳数减 1,如果减至 0,则丢弃该数据包,同时发送 ICMP 报文通知源主机。取值范围 1-255,如果设置的 TTL 值小于传输过程中需要经过的路由器数量,则该数据包在传输中就会被丢弃。

RTT(Round trip time):客户端到服务端往返所花时间。RTT 受网络传输拥塞的变化而变化,由 TCP 动态地估算

TCP 的流量控制和拥塞控制

NrFurg
1. TCP 的流量控制机制
   - 滑动窗口的原理
   - 零窗口
   - Nagle 算法

2. TCP 的拥塞控制机制
   - 慢启动
     - 每收到一个 ACK,窗口大小+1,倍增
   - 拥塞避免
   - 超时重传
     - 丢包时,慢启动阈值设定为窗口大小的一半
   - 快速重传 / 快速恢复
     - 收到三个重复的 ACK 消息

TCP 标志位:

TPC 标志位代表了当前请求的目的。一共有六种:

  1. SYN(synchronous): 发送/同步标志,用来建立连接,和 ACK 标志位搭配使用。A 请求与 B 建立连接时,SYN=1,ACK=0;B 确认与 A 建立连接时,SYN=1,ACK=1
  2. ACK(acknowledgement):确认标志,表示确认收到请求
  3. PSH(push) :表示推送操作,就是指数据包到达接收端以后,不对其进行队列处理,而是尽可能的将数据交给应用程序处理
  4. FIN(finish):结束标志,表示关闭一个 TCP 连接
  5. RST(reset):重置复位标志,用于复位对应的 TCP 连接
  6. URG(urgent):紧急标志,用于保证 TCP 连接不被中断,并且督促中间层设备尽快处理

TCP 序列号、确认号

### 作用
序列号和确认号是 TCP 实现可靠传输的依赖。TCP 使用序列号来记录发送数据包的顺序。TCP 传送一个数据包后,只有在指定时间里收到这个包的确认信息,才会将其从队列中删除,否则会重新发送该数据包。对接收方而言,通过数据分段中的序列号可以保证数据能够按照正常的顺序进行重组。

### 序列号 Sequence Number
- 在 SYN flag 置 1 时,表示当前连接的初始序列号(Initial Sequence Number,ISN)
- 在 SYN flag 置 0 时,表示当前报文段中的第一个字节的序列号

序列号的规则:

- 握手阶段,`[SYN]` 包即使没有传送数据,也会消耗一个序列号。因此,建立连接后的序列号从 `ISN+1` 开始
- 挥手阶段,`[FIN/ACK]` 包即使没有传送数据,也会消耗掉一个序列号
- 数据传输阶段,序列号 = 第一个报文段的序列号 + 已经发送的字节数
  - 比如第一个报文段的序列号为 `S`,已经发送了 100 个字节,则下一个报文段的序列号为 `S+100`
  - 如果某个报文段不携带数据,不会消耗序列号,下一个报文段还是用相同的序列号发送
  - 正常情况下,B 给 A 的确认号,就是 A 下一个报文段的序列号
- 客户端三次握手第三步的 `[ACK]` 包,和传输阶段的第一个报文段,有相同的序列号

### 确认号 Acknowledge Number
- ACK flag 置 1 时才有效,表示接收方期待的下一个报文段的序列号。一般是上次收到的报文段 seq + 1

三次握手

三次握手过程

A
  1. 第一次握手:客户端请求建立连接,向服务端发送一个同步报文(SYN synchronous 标志位记为1),同时选择一个随机数 seq(sequence number) = x 作为初始序列号
  2. 第二次握手:服务端收到连接请求报文后,如果同意建立连接,则向客户端发送同步确认报文(SYN synchronous为1,ACK acknowledgement 为1),确认号为 ack acknowledge number 为x + 1,同时选择一个随机数 seq sequence number 为y 作为初始序列号
  3. 第三次握手:客户端收到服务端的确认后,向服务端发送一个确认报文(ACK标志位 acknowledgement为1),确认号为 ack acknowledge number 为y + 1,序列号为 seq sequence number 为x + 1

这时就完成了三次握手,连接建立成功。随后,客户端和服务端的序列号将分别从 x+1y+1 开始进行传输。

客户端在两次握手就进入ESTABLISHED状态,服务端在三次握手后再进入ESTABLISHED状态,故而第三次ACK 可捎带客户端数据一起发送

为什么需要三次握手,而不是两次或四次?

F3KgOu

如果只有两次握手,那么服务端向客户端发送 SYN/ACK 报文后,就会认为连接建立。但是如果客户端没有收到报文,那么客户端是没有建立连接的。这就导致服务端会浪费资源。

  1. 确认双方的收发能力正常;

  2. 序号同步的确定性;

    缺少最后一次 ACK 则服务端无法确定对方是否收到自己的初始序号,

    数据包的序号是 TCP滑动窗口机制的基本字段

  3. 历史失效链接请求的乱序问题

    老的失效请求连接延迟,此时到达服务端,无第三次握手则服务端即开启新的连接进入 ESTABLISHED 状态,有三次握手则会发生 RST 标志 restet 终止连接

为什么不是四次握手?理论上我们总可以使用更多的通信次数交换相同的信息,使用两次握手无法建立 TCP 连接,而使用三次握手是建立连接所需要的最小次数:

  1. 第一次握手:服务端确认“自己收、客户端发”报文功能正常
  2. 第二次握手:客户端确认“自己发、自己收、服务端收、客户端发”报文功能正常,客户端认为连接已建立
  3. 第三次握手:服务端确认“自己发、客户端收”报文功能正常,此时双方均建立连接,可以正常通信

TCP 第三次握手丢包

丢包则触发 TCP重传机制:

  1. 重试一定次数后,服务端管理连接;
  2. 客户端认为建立连接,发送数据;
  3. 服务端回复 RST 报文,则客户端知悉链接失效

什么是 SYN 攻击?如何防范?

SYN 攻击属于 DOS 攻击的一种,它利用 TCP 协议缺陷,通过发送大量的半连接请求,耗费 CPU 和内存资源。

原理:

  1. 在三次握手过程中,服务器发送 [SYN/ACK] 包(第二个包)之后、收到客户端的 [ACK] 包(第三个包)之前的 TCP 连接称为半连接(half-open connect),此时服务器处于 SYN_RECV(等待客户端响应)状态。如果接收到客户端的 [ACK],则 TCP 连接成功,如果未接受到,则会不断重发请求直至成功
  2. SYN 攻击的攻击者在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 [SYN] 包,服务器回复 [SYN/ACK] 包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时
  3. 这些伪造的 [SYN] 包将长时间占用未连接队列,影响了正常的 SYN,导致目标系统运行缓慢、网络堵塞甚至系统瘫痪

检测:当在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。

防范:主要有两大类,一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固 TCP/IP 协议栈防范,如增加最大半连接数,缩短超时时间。但 SYN 攻击不能完全被阻止,除非将 TCP 协议重新设计,否则只能尽可能的减轻 SYN 攻击的危害。

四次挥手

四次挥手过程

B
  1. 第一次挥手:客户端向服务端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待服务端的确认,客户端加入 FIN_WAIT_1
    1. 序列号 seq = X,即客户端上次发送的报文的最后一个字节的序号 + 1
    2. 确认号 ack = Y, 即服务端上次发送的报文的最后一个字节的序号 + 1
  2. 第二次挥手:服务端收到连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = Y,确认号 ack = X + 1,服务端进入 CLOSE_WAIT,客户端收到后进入FIN_WAIT_2

这时 TCP 连接处于半关闭状态,即客户端到服务端的连接已经释放了,但是服务端到客户端的连接还未释放。这表示客户端已经没有数据发送了,但是服务端可能还要给客户端发送数据。

  1. 第三次挥手:服务端向客户端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待 A 的确认,客户端进入 LAST_WAIT
    1. 序列号 seq = w(未发送数据则 w==Y),即服务端上次发送的报文的最后一个字节的序号 + 1。如果半关闭状态,服务端没有发送数据,那么 w == Y
    2. 确认号 ack = X + 1,与第二次挥手相同,因为这段时间客户端没有发送数据
  2. 第四次挥手:客户端收到服务端的连接释放报文后,立即发出确认报文(ACK=1),序列号 seq = X + 1,确认号为 ack = w + 1,客户端进入 TIME_WAIT

此时,客户端就进入了 TIME-WAIT 状态。注意此时客户端到 TCP 连接还没有释放,必须经过 2*MSL(最长报文段生命周期)的时间后,才进入 CLOSED 状态。而服务端只要收到客户端发出的确认,就立即进入 CLOSED 状态。可以看到,服务端结束 TCP 连接的时间要比客户端早一些。

TCP 规定,[FIN/ACK] 包即使没有传送数据,也会消耗掉一个序列号。[FIN/ACK] 包是第一、三次挥手:

  1. 第一次挥手时,客户端的序列号 seq = X,消耗一个序列号。因此:
    1. 第二次挥手时,服务端的确认号 ack = X + 1
    2. 第四次挥手时,客户端的序列号 seq = X + 1
  2. 第三次挥手时,服务端的序列号 seq = w,消耗一个序列号。因此:
    1. 第四次挥手时,客户端的确认号 ack = w + 1

为什么第四次挥手,客户端的 TIME-WAIT 状态必须等待 2MSL 的时间才能返回到 CLOSED 状态?

为什么四次挥手——>因为 TCP 是全双工的,一方关闭连接后,另一方还可以继续发送数据。所以四次挥手,将断开连接分成两个独立的过程。

2MSL——>主要有两个原因:

(1) 确保 ACK 报文能够到达服务端,从而使服务端正常关闭连接。

第四次挥手时,客户端第四次挥手的 ACK 报文不一定会到达服务端。服务端会超时重传 FIN/ACK 报文,此时如果客户端已经断开了连接,那么就无法响应服务端的二次请求,这样服务端迟迟收不到 FIN/ACK 报文的确认,就无法正常断开连接。

MSL 是报文段在网络上存活的最长时间。客户端等待 2MSL 时间,即「客户端 ACK 报文 1MSL 超时 + 服务端 FIN 报文 1MSL 传输」,就能够收到服务端重传的 FIN/ACK 报文,然后客户端重传一次 ACK 报文,并重新启动 2MSL 计时器。如此保证服务端能够正常关闭。

那如果服务端重发的 FIN 没有成功地在 2MSL 时间里传给客户端,会怎样?服务端会继续超时重试直到断开连接,见下文。

(2) 防止已失效的连接请求报文段出现在之后的连接中。

TCP 要求在 2MSL 内不使用相同的序列号。客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以保证本连接持续的时间内产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。或者即使收到这些过时的报文,也可以不处理它。

如果已经建立了连接,但是客户端出现故障了怎么办?

或者说,如果三次握手阶段、四次挥手阶段的包丢失了怎么办?比如上面描述的“服务端重发 FIN”的问题。

简而言之,通过定时器 + 超时重试机制,尝试获取确认,直到最后会自动断开连接。

具体而言,TCP 设有一个保活计时器。服务器每收到一次客户端的数据,都会重新复位这个计时器,时间通常是设置为 2 小时。若 2 小时还没有收到客户端的任何数据,服务器就开始重试:每隔 75 分钟发送一个探测报文段,若一连发送 10 个探测报文后客户端依然没有回应,那么服务器就认为连接已经断开了。

TCP 的粘包问题

TCP 是基于字节流的,数据块是没有边界、没有结构的字节流,因此可能产生粘包:

  1. 发送方为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据包,合并成一个大的数据包一次性发送。

    当应用层协议通过 TCP 协议传输数据时,实际上待发送的数据先被写入了 TCP 协议的缓冲区,如果用户开启了 Nagle 算法,那么 TCP 协议可能不会立刻发送写入的数据,它会等待缓冲区中数据超过最大数据段(MSS)或者上一个数据段被 ACK 时才会发送缓冲区中的数据。

  2. 接收方不能及时读取数据,导致缓冲区中的多个包粘连。

解决方法

  1. 发送方关闭 Nagle 算法
  2. 应用层定义消息边界,最常见的两种解决方案就是基于长度或者基于终结符(Delimiter)
    1. 基于长度的实现有两种方式,一种是使用固定长度;另一种方式是使用不固定长度,但是需要在应用层协议的协议头中增加表示负载长度的字段,HTTP 协议的消息边界就是基于长度实现的
    2. HTTP 协议除了使用基于长度的方式实现边界,也会使用基于终结符的策略,当 HTTP 使用块传输(Chunked Transfer)机制时,HTTP 头中就不再包含 Content-Length 了,它会使用负载大小为 0 的 HTTP 消息作为终结符表示消息的边界

除了这两种方式之外,我们可以基于特定的规则实现消息的边界,例如:使用 TCP 协议发送 JSON 数据,接收方可以根据接收到的数据是否能够被解析成合法的 JSON 判断消息是否终结。

但值得注意的是,粘包并不是 TCP 协议本身的“问题”,而是一个“现象”。TCP 本身面向字节流的特性,导致会有所谓的“粘包”问题,需要应用层进行拆分。所以也有一种说法是“TCP 粘包是一个伪命题”。

**为什么 UDP 协议没有粘包问题?**UDP 是面向报文的,应用层交给 UDP 多长的报文,UDP 就照样发送,既不合并,也不拆分,而是保留这些报文的边界。

TCP 如何保证传输的可靠性?

  1. 序列号:解决乱序问题
  2. 确认号 / 超时重传机制:解决丢包问题

TCP、UDP 对比

  1. TCP:面向连接的、可靠的、基于字节流的传输层通信协议
  2. UDP:无连接的、不可靠的、基于报文的传输层通信协议
  3. 面向字节流:TCP 将要发送的数据视为无结构的字节流,如果发送的数据太长,就拆分发送,如果发送的数据太短,则积累较多的字节后再发送
  4. 面向报文:UDP 一次发送一个报文,不管多大,都以报文为发送单位
TCP UDP
连接性 面向连接 无连接
可靠性 可靠 不可靠
传输方式 面向字节流 面向报文(保留报文的边界)
传输速度
双工性 全双工 一对一、一对多、多对一、多对多
流量控制 / 拥塞控制
应用场景 对效率要求相对低,但是对准确性要求高的场景;或是要求有连接的场景。如文件传输、发送邮件等 对效率要求相对高,对准确性要求相对低的场景。如即时通信、直播等
应用层协议 SMTP(电子邮件)、TELNET(远程登录控制)、HTTP、FTP DNS、TFTP(文件传输)、DHCP(动态主机配置)...

HTTP 请求方法

HTTP 请求方法表明了要对给定资源执行的操作,每一个请求方法都实现了不同的语义。包括:GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS,以及不常用的 CONNECT、TRACE。

方法 含义
GET 获取数据
HEAD GET 类似,但只返回响应头
POST 提交表单
PUT 用一个新的资源完全替换掉服务器的资源
DELETE 删除资源
CONNECT 建立一个 tunnel
OPTIONS 询问服务器支持哪些方法
TRACE 发起环回诊断,主要用于诊断
PATCH 对服务器资源进行部分更新

GET 和 POST 的区别

GET POST
应用 获取服务器的指定数据 添加 / 修改服务器的数据
历史记录 / 书签 可保留在浏览器历史记录中,或者收藏为书签 不可以
Cacheable 会被浏览器缓存 不会缓存
幂等 幂等,不会改变服务器上的资源 非幂等,会对服务器资源进行改变
后退 / 刷新 后退或刷新时,GET 是无害的 后退或刷新时,POST 会重新提交表单
参数位置 query 中(直接明文暴露在链接中) query 或 body 中
参数长度 2KB(2048 个字符) 无限制

二者都是用来跟踪浏览器用户身份的会话方式。

Cookie:

  1. 存在浏览器里,可以设置过期时间
  2. 每次访问服务器时,浏览器会自动在 header 中携带 cookie
  3. 如果浏览器禁用了 cookie,可以使用 URL 重写机制,将信息保存在 URL 里

Session:

  1. 存在服务端,由服务器维护,一段时间后 session 就失效了
  2. 本质上,session 还是通过 cookie 实现的。浏览器的 cookie 中只保存一个 sessionId,所有其他信息均保存在服务端,由 sessionId 标识
  3. Session 失效,其实是服务器设置了失效时间。如果用户长时间不和服务器交互(比如 30 分钟),那么 session 就会被销毁;交互的话,就会刷新 session

从输入一个 URL 到页面加载完成的过程

C
  1. 用户在某个标签页输入 URL 并回车后,浏览器主进程会新开一个网络线程,发起 HTTP 请求
  2. 浏览器会进行 DNS 查询,将域名解析为 IP 地址
  3. 浏览器获得 IP 地址后,向服务器请求建立 TCP 连接
  4. 浏览器向服务器发起 HTTP 请求
  5. 服务器处理请求,返回 HTTP 响应
  6. 浏览器的渲染进程解析并绘制页面
  7. 如果遇到 JS/CSS/图片 等静态资源的引用链接,重复上述过程,向服务器请求这些资源

介绍一下 HTTP 协议

HTTP 协议是基于 TCP 协议实现的,它是一个超文本传输协议,其实就是一个简单的请求-响应协议,它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应

它主要是负责点对点之间通信的。

超文本就是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本。比如说html,内部定义了很多图片视频的链接,放在浏览器上就呈现出了画面。

协议就是约定俗称的东西,比如说 moon 要给读者送一本书,读者那里只接受顺丰快递,那么 moon 觉得可以,发快递的时候选择的顺丰,那么我们彼此之间共同约定好的就叫做协议。

传输这个就很好理解了,比如刚才举的例子,将书发给读者,要通过骑车或者飞机的方式,传递的这个过程就是运输。

GET 和 POST有什么区别?

GET 和 POST 本质上就是 TCP 链接,并无差别。

但是由于 HTTP 的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

区别 GET POST
数据传输方式 从服务器获取数据 向服务器提交数据
对数据长度的限制 当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符) 无限制
对数据类型的限制 只允许 ASCII 字符 无限制
安全性 较差,所发送的数据是 URL 的一部分,会显示在网页上 较好 参数不会被保存在浏览器历史或 WEB 服务器日志中
可见性 显示在 URL 上 不显示
收藏为书签 可以 不可以
历史记录 可以被保留在历史记录当中 不可以被保留
缓存 能被缓存 不可以被缓存

PING 的作用?

PING 主要的作用就是测试在两台主机之间能否建立连接,如果 PING 不通就无法建立连接。

它其实就是向目的主机发送多个 ICMP 回送请求报文

  1. 如果没有响应则无法建立连接
  2. 如果有响应就可以根据目的主机返回的回送报文的时间和成功响应的次数估算出数据包往返时间及丢包率

HTTP1.1 和 HTTP1.0 的区别有哪些?

D
  1. 长链接

    1. 早期 HTTP1.0 的每一次请求都伴随着一次三次握手的过程,并且是串行的请求,增加了不必要的性能开销
    2. HTTP1.1 新增了长链接的通讯方式,减少了性能损耗
  2. 管道

    1. HTTP1.0 只有串行发送,没有管道
    2. HTTP1.1 增加了管道的概念,使得在同一个 TCP 链接当中可以同时发出多个请求
  3. 断点续传

    1. HTTP1.0 不支持断点续传
    2. HTTP1.1 新增了 range 字段,用来指定数据字节位置,开启了断点续传的时代
  4. Host头处理

    1. HTTP1.0 任务主机只有一个节点,所以并没有传 HOST
    2. HTTP1.1 时代,虚拟机技术越来越发达,一台机器上也有可能有很多节点,故增加了 HOST 信息
  5. 缓存处理

    1. 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准
    2. HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  6. 错误状态响应码

    1. 在HTTP1.1中新增了24个错误状态响应码,如410(Gone)表示服务器上的某个资源被永久性的删除等。

HTTPS 和 HTTP 的区别是什么?

E
  1. SSL安全协议

    HTTP 是超⽂本传输协议,信息是明⽂传输,存在安全⻛险的问题。

    HTTPS 则解决 HTTP 不安全的缺陷,在TCP 和 HTTP ⽹络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输

  2. 建立连接

    HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。

    HTTPS 在 TCP 三次握⼿之后,还需进⾏ SSL/TLS握⼿过程,才可进⼊加密报⽂传输。

  3. 端口号

    HTTP 的端⼝号是 80

    HTTPS 的端⼝号是 443

  4. CA证书

    *HTTPS 协议需要向 CA(证书权威。机构)申请数字证书**来保证服务器的身份是可信的。

HTTP2 和 HTTP1.1 的区别是什么?

G
  1. 头部压缩

    1. 在 HTTP2 当中,如果你发出了多个请求,并且它们的头部(header)是相同的,那么 HTTP2 协议会帮你消除同样的部分。(其实就是在客户端和服务端维护一张索引表来实现)
  2. 二进制格式

    HTTP1.1 采用明文的形式

    HTTP/2 全⾯采⽤了⼆进制格式,头信息和数据体都是⼆进制

  3. 数据流

    HTTP/2 的数据包不是按顺序发送的,同⼀个连接⾥⾯连续的数据包,可能属于不同的回应。(对数据包做了标记,标志其属于哪一个请求,其中规定客户端发出的数据流编号为奇数,服务器发出的数据流编号为偶数。客户端还可以指定数据流的优先级,优先级⾼的请求,服务器就先响应该请求)

  4. IO多路复用

    如:在⼀个连接中,服务器收到了客户端 A 和 B 的两个请求,但是发现在处理 A 的过程中⾮常耗时,索性就先回应 A 已经处理好的部分,再接着回应 B 请求,最后再回应 A 请求剩下的部分。

    HTTP/2 可以在⼀个连接中并发多个请求或回应

  5. 服务器推送

    服务器可以主动向客户端发送请求

HTTP/2与HTTP/1相比,改进在哪?为什么会更快?

主要的改进包括:

  1. 多路复用,允许通过单一的HTTP/2连接发起多重的请求-响应消息。而HTTP/1.1协议中,
    浏览器客户端在同一时间内,针对同一域名下的请求数量有一定的数量限制。超过限制数目
    的请求会被阻塞。(解决办法:CDN使用多个域名)
  2. 二进制分帧,HTTP/2会将所有传输的信息分割成更小的消息和帧,并对他们采用二进制
    格式的编码,其中HTTP/1.1中的首部信息会被封装到HEADER frame,而body则会封装进
    DATA frame。头部进行压缩,使用HPACK算法。

HTTP3 和 HTTP2 的区别是什么?

H
  1. 协议不同

    HTTP2 是基于 TCP 协议实现的

    HTTP3 是基于 UDP 协议实现的

  2. QUIC

    HTTP3 新增了 QUIC 协议**来实现可靠性的传输

  3. 握手次数

    HTTP2 是基于 HTTPS 实现的,建立连接需要先进行 TCP 3次握手,然后再进行 TLS 3次握手,总共6次握手

    HTTP3 只需要 QUIC 的3次握手

TCP 半连接队列和全连接队列是什么?

AA

服务端收到客户端发出的 SYN 请求后,会把这个连接信息存储到半链接队列(SYN 队列)

服务端收到第三次握⼿的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到全连接队列(accept 队列),等待进程调⽤ accept 函数时把连接取出来。

这两个队列都是有大小限制的,当超过容量后就会将链接丢弃,或者返回 RST 包。

粘包/拆包是怎么发生的?怎么解决这个问题?

TCP 发送数据时会根据 TCP 缓冲区的实际情况进行包的划分,一个完整的包可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是 TCP 粘包和拆包问题。

BB

发生 TCP 粘包原因:
1. 发送的数据小于 TCP 缓冲区大小,TCP将缓冲区中的数据(数据属于多条业务内容)一次发送出去可能就会发生粘包。
2. 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

发生 TCP 拆包原因:
1. 待发送数据大于最大报文长度,TCP 在传输前将进行拆包。
2. 发送的数据大于 TCP 发送缓冲区剩余空间大小,将会发生拆包。

解决方案:

CC
  1. 发送端给每个数据包添加包首部,首部中包含数据包的长度,这样接收端在接收到数据后,通过该字段就可以知道每个数据包的实际长度了。
  2. 发送端将每个数据包设置固定长度,这样接收端每次从读取固定长度的数据把每个数据包拆分开。
  3. 可以在数据包之间设置边界,如添加特殊符号,接收端可以通过这个特殊符号来拆分包。

浏览器地址栏输入网站按回车后发生了什么?

DD
  1. 解析网址,生成 HTTP 请求信息
  2. 根据 DNS 服务器查询真实请求的 IP 地址,如果本地服务器有缓存则直接返回
  3. 得到了 IP 以后,向服务器发送 TCP 连接,TCP 连接经过三次握手。
  4. 接受 TCP 报文后,对连接进行处理,对 HTTP 协议解析
  5. 服务器返回响应
  6. 浏览器*接受响应,显示页面,渲染页面**