计网

TCP/IP 四层模型

TCP/IP 四层模型

为什么网络要分层?

  • 各层之间相互独立:各层之间相互独立,各层之间不需要关心其他层是如何实现的,只需要知道自己如何调用下层提供好的功能就可以了(可以简单理解为接口调用)。这个和我们对开发时系统进行分层是一个道理。

  • 提高了灵活性和可替换性:每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。并且,每一层都可以根据需要进行修改或替换,而不会影响到整个网络的结构。这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。

  • 大问题化小:分层可以将复杂的网络问题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义。

应用层

应用层常见协议

传输层

传输层常见协议

  • TCP(Transmission Control Protocol,传输控制协议 ):提供 面向连接 的,可靠 的数据传输服务。

  • UDP(User Datagram Protocol,用户数据协议):提供 无连接 的,尽最大努力 的数据传输服务(不保证数据传输的可靠性),简单高效

网络层

网络层常见协议

  • IP(Internet Protocol,网际协议):TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。

  • ARP(Address Resolution Protocol,地址解析协议):ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。

  • ICMP(Internet Control Message Protocol,互联网控制报文协议):一种用于传输网络状态和错误消息的协议,常用于网络诊断和故障排除

  • NAT(Network Address Translation,网络地址转换协议):NAT 协议的应用场景如同它的名称——网络地址转换,应用于内部网到外部网的地址转换过程中。

  • OSPF(Open Shortest Path First,开放式最短路径优先):一种内部网关协议(Interior Gateway Protocol,IGP),也是广泛使用的一种动态路由协议,基于链路状态算法,考虑了链路的带宽、延迟等因素来选择最佳路径。

  • RIP(Routing Information Protocol,路由信息协议):一种内部网关协议(Interior Gateway Protocol,IGP),也是一种动态路由协议,基于距离向量算法,使用固定的跳数作为度量标准,选择跳数最少的路径作为最佳路径。

  • BGP(Border Gateway Protocol,边界网关协议):一种用来在路由选择域之间交换网络层可达性信息(Network Layer Reachability Information,NLRI)的路由选择协议,具有高度的灵活性和可扩展性。


HTTP

从输入 URL 到页面展示到底发生了什么?

img

总体来说分为以下几个步骤:

  1. 在浏览器中输入指定网页的 URL。
  2. 浏览器通过 DNS 协议,获取域名对应的 IP 地址。
  3. 浏览器根据 IP 地址和端口号,向目标服务器发起一个 TCP 连接请求。
  4. 浏览器在 TCP 连接上,向服务器发送一个 HTTP 请求报文,请求获取网页的内容。
  5. 服务器收到 HTTP 请求报文后,处理请求,并返回 HTTP 响应报文给浏览器。
  6. 浏览器收到 HTTP 响应报文后,解析响应体中的 HTML 代码,渲染网页的结构和样式,同时根据 HTML 中的其他资源的 URL(如图片、CSS、JS 等),再次发起 HTTP 请求,获取这些资源的内容,直到网页完全加载显示。
  7. 浏览器在不需要和服务器通信时,可以主动关闭 TCP 连接,或者等待服务器的关闭请求。

HTTP 状态码

类别 举例
1XX 信息性状态码
2XX 成功状态码 200 OK,201 Created,202 Accepted,204 No Content
3XX 重定向状态码 301 Moved Permanently永久重定向,302 Found 临时
4XX 客户端错误状态码 400 Bad Request,401 Unauthorized,403 Forbidden,404 Not Found,409 Conflict
5XX 服务器错误状态码 500 Internal Server Error,502 Bad Gateway

HTTPS

  • HTTPS 协议之所以是安全的是因为 HTTPS 协议会对传输的数据进行加密,而加密过程是使用了非对称加密实现。但其实,HTTPS 在内容传输的加密上使用的是对称加密非对称加密只作用在证书验证阶段。

使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。

HTTPS传输流程


  1. 前置:服务器已向 CA 申请并获得 X.509 证书
    证书内容 = 站点域名 + 服务器公钥 Pk + CA 签名(用 CA 私钥对前两项的哈希签名)。

  1. 客户端 → 服务器:ClientHello
    • 支持的 TLS 版本、
    • 对称算法列表(TLS_AES_256_GCM_SHA384…)、
    • 客户端随机数 cr(32 B)、
    • 通过 SNI 告诉服务器目标域名。

  1. 服务器 → 客户端:ServerHello + Certificate + CertificateVerify + Finished(一次航班发完)
    a) ServerHello:选定的算法、服务器随机数 sr
    b) Certificate:服务器证书(含 Pk)。
    c) CertificateVerify:服务器用 自己的私钥 SkTranscript-Hash(ClientHello..Certificate) 签名,证明“我拥有与 Pk 对应的 Sk”。
    d) Finished:服务器已握手的 MAC,密钥推导见下。

  1. 客户端验证
    • 用本地 CA 公钥解开证书里的签名 → 得到哈希,与本地哈希计算证书其他内容比对 → 证书合法。
    • 用证书里的 Pk 解开 CertificateVerify 里的签名 → 验证成功 → 服务器身份可信。
    • 检查域名、有效期、吊销列表(OCSP/CRL)。

  1. 密钥交换(TLS 1.3 只有 ECDHE)
    • 客户端生成一次性 ECDHE 私钥 ec_sk、公钥 ec_pk
    • ec_pk 放在 ClientKeyShare 扩展里发给服务器(已加密)。
    • 服务器同样生成自己的 ec_pk’ec_sk’,并回传 ec_pk’
    • 双方本地计算共享密钥:
      shared_secret = ECDH(ec_sk, ec_pk’) = ECDH(ec_sk’, ec_pk)
    • 再用 shared_secret + cr + sr 通过 HKDF 导出三条密钥:
      • client_handshake_traffic_secret
      • server_handshake_traffic_secret
      • master_secret(后续应用数据密钥)

  1. 客户端 → 服务器:Finished(握手结束)
    client_handshake_traffic_secret 计算 MAC 发送 Finished,服务器验证通过后双方握手完成。

  1. 应用数据传输
    • master_secret 派生 client_application_traffic_secretserver_application_traffic_secret
    • 对称加密(AES-GCM/ChaCha20-Poly1305)+ 认证标签,所有 HTTP 请求/响应都用这两把对称密钥加解密
    • client_application_traffic_secret
      – 客户端用它加密请求报文
      – 服务器收到后用同一把密钥解密请求

  1. 会话恢复(可选,0-RTT)
    服务器给客户端一张 PSK ticket(用 resumption_master_secret 加密),下次客户端直接带 PSK + ECDHE 公钥,第一条请求就能携带加密数据

关键结论

  • CA 只参与「证书验证」:客户端用本地 CA 公钥解签名 → 确认服务器公钥 Pk 可信。
  • 真正加密 HTTP 数据的是「ECDHE 协商出的对称密钥」,公私钥仅用于 身份认证安全交换 ECDHE 公钥

HTTP 和 HTTPS 区别

  • 端口号:HTTP 默认是 80,HTTPS 默认是 443。

  • URL 前缀:HTTP 的 URL 前缀是 https://,HTTPS 的 URL 前缀是 https://

  • 安全性和资源消耗:HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。

  • SEO(搜索引擎优化):搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。

WebSocket

工作过程可以分为以下几个步骤:

  1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 Upgrade: websocketSec-WebSocket-Key 等字段,表示要求升级协议为 WebSocket;
  2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket,它将回复一个 HTTP 101 状态码,响应头中包含 ,Connection: UpgradeSec-WebSocket-Accept: xxx 等字段、表示成功升级到 WebSocket 协议。
  3. 客户端和服务器之间建立了一个 WebSocket 连接,可以进行双向的数据传输。数据以帧(frames)的形式进行传送,WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
  4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。

另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。

TCP三次握手,四次挥手

连接:三次握手

在这里插入图片描述

建立一个 TCP 连接需要“三次握手”,缺一不可:

  1. 第一次握手 (SYN): 客户端向服务端发送一个 SYN(Synchronize Sequence Numbers)报文段,其中包含一个由客户端随机生成的初始序列号(Initial Sequence Number, ISN),例如 seq=x。发送后,客户端进入 SYN_SEND 状态,等待服务端的确认。

  2. 第二次握手 (SYN+ACK)

    : 服务端收到 SYN 报文段后,如果同意建立连接,会向客户端回复一个确认报文段。该报文段包含两个关键信息:

    • SYN:服务端也需要同步自己的初始序列号,因此报文段中也包含一个由服务端随机生成的初始序列号,例如 seq=y。
    • ACK (Acknowledgement):用于确认收到了客户端的请求。其确认号被设置为客户端初始序列号加一,即 ack=x+1。
    • 发送该报文段后,服务端进入 SYN_RECV 状态。
  3. 第三次握手 (ACK): 客户端收到服务端的 SYN+ACK 报文段后,会向服务端发送一个最终的确认报文段。该报文段包含确认号 ack=y+1。发送后,客户端进入 ESTABLISHED 状态。服务端收到这个 ACK 报文段后,也进入 ESTABLISHED 状态。

至此,双方都确认了连接的建立,TCP 连接成功创建,可以开始进行双向数据传输。


三次握手原因

1. 确认双方的收发能力,并同步初始序列号 (ISN)

TCP 通信依赖序列号来保证数据的有序和可靠。三次握手是双方交换和确认彼此初始序列号(ISN)的过程,通过这个过程,双方也间接验证了各自的收发能力。

  • 第一次握手 (客户端 → 服务器)

    :客户端发送 SYN 包。

    • 服务器:能确认客户端的发送能力正常,自己的接收能力正常。
    • 客户端:无法确认任何事。
  • 第二次握手 (服务器 → 客户端)

    :服务器回复 SYN+ACK 包。

    • 客户端:能确认自己的发送和接收能力正常,服务器的接收和发送能力正常。
    • 服务端:能确认对方发送能力正常,自己接收能力正常
  • 第三次握手 (客户端 → 服务器)

    :客户端发送 ACK 包。

    • 客户端:能确认双方发送和接收能力正常。
    • 服务端:能确认双方发送和接收能力正常。

经过这三次交互,双方都确认了彼此的收发功能完好,并完成了初始序列号的同步,为后续可靠的数据传输奠定了基础。

2. 防止已失效的连接请求被错误地建立

这是“为什么不能是两次握手”的关键原因。

设想一个场景:客户端发送的第一个连接请求(SYN1)因网络延迟而滞留,于是客户端重发了第二个请求(SYN2)并成功建立了连接,数据传输完毕后连接被释放。此时,延迟的 SYN1 才到达服务端。

  • 如果是两次握手:服务端收到这个失效的 SYN1 后,会误认为是一个新的连接请求,并立即分配资源、建立连接。但这将导致服务端单方面维持一个无效连接,白白浪费系统资源,因为客户端并不会有任何响应。
  • 有了第三次握手:服务端收到失效的 SYN1 并回复 SYN+ACK 后,会等待客户端的最终确认(ACK)。由于客户端当前并没有发起连接的意图,它会忽略这个 SYN+ACK 或者发送一个 RST (Reset) 报文。这样,服务端就无法收到第三次握手的 ACK,最终会超时关闭这个错误的连接,从而避免了资源浪费。

因此,三次握手是确保 TCP 连接可靠性的最小且必需的步骤。它不仅确认了双方的通信能力,更重要的是增加了一个最终确认环节,以防止网络中延迟、重复的历史请求对连接建立造成干扰。


断开:四次挥手

在这里插入图片描述

断开一个 TCP 连接则需要“四次挥手”,缺一不可:

  1. 第一次挥手 (FIN):当客户端(或任何一方)决定关闭连接时,它会向服务端发送一个 FIN(Finish)标志的报文段,表示自己已经没有数据要发送了。该报文段包含一个序列号 seq=u。发送后,客户端进入 FIN-WAIT-1 状态。
  2. 第二次挥手 (ACK):服务端收到 FIN 报文段后,会立即回复一个 ACK 确认报文段。其确认号为 ack=u+1。发送后,服务端进入 CLOSE-WAIT 状态。客户端收到这个 ACK 后,进入 FIN-WAIT-2 状态。此时,TCP 连接处于**半关闭(Half-Close)**状态:客户端到服务端的发送通道已关闭,但服务端到客户端的发送通道仍然可以传输数据。
  3. 第三次挥手 (FIN):当服务端确认所有待发送的数据都已发送完毕后,它也会向客户端发送一个 FIN 报文段,表示自己也准备关闭连接。该报文段同样包含一个序列号 seq=y。发送后,服务端进入 LAST-ACK 状态,等待客户端的最终确认。
  4. 第四次挥手:客户端收到服务端的 FIN 报文段后,会回复一个最终的 ACK 确认报文段,确认号为 ack=y+1。发送后,客户端进入 TIME-WAIT 状态。服务端在收到这个 ACK 后,立即进入 CLOSED 状态,完成连接关闭。客户端则会在 TIME-WAIT 状态下等待 2MSL(Maximum Segment Lifetime,报文段最大生存时间)后,才最终进入 CLOSED 状态。

只要四次挥手没有结束,客户端和服务端就可以继续传输数据!


为什么第四次挥手客户端需要等待 2*MSL

第四次挥手时,客户端发送给服务端的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN。

MSL(Maximum Segment Lifetime) : 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接