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 到页面展示到底发生了什么?

总体来说分为以下几个步骤:
- 在浏览器中输入指定网页的 URL。
- 浏览器通过 DNS 协议,获取域名对应的 IP 地址。
- 浏览器根据 IP 地址和端口号,向目标服务器发起一个 TCP 连接请求。
- 浏览器在 TCP 连接上,向服务器发送一个 HTTP 请求报文,请求获取网页的内容。
- 服务器收到 HTTP 请求报文后,处理请求,并返回 HTTP 响应报文给浏览器。
- 浏览器收到 HTTP 响应报文后,解析响应体中的 HTML 代码,渲染网页的结构和样式,同时根据 HTML 中的其他资源的 URL(如图片、CSS、JS 等),再次发起 HTTP 请求,获取这些资源的内容,直到网页完全加载显示。
- 浏览器在不需要和服务器通信时,可以主动关闭 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传输流程
- 前置:服务器已向 CA 申请并获得 X.509 证书
证书内容 = 站点域名 + 服务器公钥 Pk + CA 签名(用 CA 私钥对前两项的哈希签名)。
- 客户端 → 服务器:ClientHello
- 支持的 TLS 版本、
- 对称算法列表(
TLS_AES_256_GCM_SHA384…)、 - 客户端随机数 cr(32 B)、
- 通过 SNI 告诉服务器目标域名。
- 服务器 → 客户端:ServerHello + Certificate + CertificateVerify + Finished(一次航班发完)
a) ServerHello:选定的算法、服务器随机数 sr。
b) Certificate:服务器证书(含 Pk)。
c) CertificateVerify:服务器用 自己的私钥 Sk 对Transcript-Hash(ClientHello..Certificate)签名,证明“我拥有与 Pk 对应的 Sk”。
d) Finished:服务器已握手的 MAC,密钥推导见下。
- 客户端验证
- 用本地 CA 公钥解开证书里的签名 → 得到哈希,与本地哈希计算证书其他内容比对 → 证书合法。
- 用证书里的 Pk 解开 CertificateVerify 里的签名 → 验证成功 → 服务器身份可信。
- 检查域名、有效期、吊销列表(OCSP/CRL)。
- 密钥交换(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(后续应用数据密钥)
- 客户端 → 服务器:Finished(握手结束)
用 client_handshake_traffic_secret 计算 MAC 发送 Finished,服务器验证通过后双方握手完成。
- 应用数据传输
- 用 master_secret 派生 client_application_traffic_secret 与 server_application_traffic_secret。
- 对称加密(AES-GCM/ChaCha20-Poly1305)+ 认证标签,所有 HTTP 请求/响应都用这两把对称密钥加解密。
client_application_traffic_secret
– 客户端用它加密请求报文
– 服务器收到后用同一把密钥解密请求
- 会话恢复(可选,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
工作过程可以分为以下几个步骤:
- 客户端向服务器发送一个 HTTP 请求,请求头中包含
Upgrade: websocket和Sec-WebSocket-Key等字段,表示要求升级协议为 WebSocket; - 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket,它将回复一个 HTTP 101 状态码,响应头中包含 ,
Connection: Upgrade和Sec-WebSocket-Accept: xxx等字段、表示成功升级到 WebSocket 协议。 - 客户端和服务器之间建立了一个 WebSocket 连接,可以进行双向的数据传输。数据以帧(frames)的形式进行传送,WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
- 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。
另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。
TCP三次握手,四次挥手
连接:三次握手

建立一个 TCP 连接需要“三次握手”,缺一不可:
第一次握手 (SYN): 客户端向服务端发送一个 SYN(Synchronize Sequence Numbers)报文段,其中包含一个由客户端随机生成的初始序列号(Initial Sequence Number, ISN),例如 seq=x。发送后,客户端进入 SYN_SEND 状态,等待服务端的确认。
第二次握手 (SYN+ACK)
: 服务端收到 SYN 报文段后,如果同意建立连接,会向客户端回复一个确认报文段。该报文段包含两个关键信息:
- SYN:服务端也需要同步自己的初始序列号,因此报文段中也包含一个由服务端随机生成的初始序列号,例如 seq=y。
- ACK (Acknowledgement):用于确认收到了客户端的请求。其确认号被设置为客户端初始序列号加一,即 ack=x+1。
- 发送该报文段后,服务端进入 SYN_RECV 状态。
第三次握手 (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 连接则需要“四次挥手”,缺一不可:
- 第一次挥手 (FIN):当客户端(或任何一方)决定关闭连接时,它会向服务端发送一个 FIN(Finish)标志的报文段,表示自己已经没有数据要发送了。该报文段包含一个序列号 seq=u。发送后,客户端进入 FIN-WAIT-1 状态。
- 第二次挥手 (ACK):服务端收到 FIN 报文段后,会立即回复一个 ACK 确认报文段。其确认号为 ack=u+1。发送后,服务端进入 CLOSE-WAIT 状态。客户端收到这个 ACK 后,进入 FIN-WAIT-2 状态。此时,TCP 连接处于**半关闭(Half-Close)**状态:客户端到服务端的发送通道已关闭,但服务端到客户端的发送通道仍然可以传输数据。
- 第三次挥手 (FIN):当服务端确认所有待发送的数据都已发送完毕后,它也会向客户端发送一个 FIN 报文段,表示自己也准备关闭连接。该报文段同样包含一个序列号 seq=y。发送后,服务端进入 LAST-ACK 状态,等待客户端的最终确认。
- 第四次挥手:客户端收到服务端的 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 连接