背网络层次不难,难的是把它们串成一次真实请求:浏览器如何找到服务器,数据怎样逐层封装,TCP 为什么要握手,页面打不开时又该从哪里查起。本文沿着一次 HTTPS 请求,把这些问题连成一条线。

1. 先把分层模型放回实际网络

OSI 七层模型适合解释职责,日常排障更常按 TCP/IP 四层模型思考。两者不是两套互相竞争的协议,而是观察同一通信过程的不同粒度。

TCP/IP 层次 大致对应的 OSI 层 典型协议或对象 主要问题
应用层 应用、表示、会话层 HTTP、TLS、DNS 传什么、怎样解释
传输层 传输层 TCP、UDP 哪个进程、是否可靠
网际层 网络层 IPv4、IPv6、ICMP 发往哪台主机、怎样路由
网络接口层 数据链路、物理层 Ethernet、Wi-Fi、ARP 下一跳是谁、怎样在链路上传输

发送时,应用数据会依次包进传输层报文段、IP 数据包和链路层帧;接收方再反向拆开。每一层只处理自己的地址与控制信息:端口定位进程,IP 地址定位主机,MAC 地址负责当前链路上的交付。

一个容易混淆的点是:交换机主要依据 MAC 地址转发帧,路由器主要依据 IP 地址转发数据包。数据跨过路由器后,链路层帧会重新封装,但端到端的源、目的 IP 通常保持不变;经过 NAT 时则可能被改写。

2. 输入网址后发生了什么

以访问 https://eulersail.com/ 为例,可以把主线压缩成下面几步:

DNS 先把域名解析成 IP 地址;本机根据路由表决定数据从哪个接口发出,并在局域网内解析下一跳的链路地址。随后建立传输连接。HTTPS 还要在 TCP 之上完成 TLS 握手,协商加密参数并验证服务器身份,最后才交换 HTTP 请求和响应。

因此,“网页打不开”并不等于“服务器宕机”。DNS、路由、端口、TLS 或 HTTP 任一环节失败,都可能在浏览器里表现为打不开。

3. TCP 三次握手

TCP 是面向连接的可靠字节流协议。连接建立时,双方不仅要确认对端可达,还要分别同步自己这一方向的初始序列号。

  1. 客户端发送 SYN,声明自己的初始序列号 x
  2. 服务器回复 SYN + ACK:确认收到了 x,同时声明自己的初始序列号 y
  3. 客户端发送 ACK,确认收到了 y,双方进入 ESTABLISHED
交互时间线

逐步走完三次握手

点击发送报文,观察两端各自确认了什么,而不只是背 SYN、ACK 的顺序。

  1. 客户端SYN · Seq=x服务器
  2. 客户端SYN + ACK · Seq=y · Ack=x+1服务器
  3. 客户端ACK · Ack=y+1服务器

第三次不能简单省略。服务器收到最后一个 ACK 后,才知道自己的发送方向也已被客户端确认。序列号与连接状态还能帮助协议栈识别网络中迟到的旧报文,避免把它误当作新连接的数据。

握手只说明连接已经建立,并不保证应用一定正常。端口可以接受 TCP 连接,但应用仍可能返回 HTTP 500,或在 TLS 阶段因证书、协议不兼容而失败。

4. “可靠传输”具体可靠在哪里

TCP 的可靠不是“网络永不丢包”,而是协议在丢包、乱序和接收能力变化时尽量向应用提供有序、不重复的字节流。

机制 作用
字节序列号 标记数据在字节流中的位置,用于排序和去重
确认应答 通常用累计 ACK 表示下一段期望收到的字节
超时与重传 未及时确认的数据会重新发送
快速重传 从重复 ACK 等信号更快推断丢失,而不只等待超时
校验和 检测传输中的比特错误
接收窗口 让发送方不要压垮接收方,这是流量控制
拥塞控制 根据网络状况调节发送速度,避免加剧拥塞

流量控制和拥塞控制解决的是两个问题:前者关心“接收端吃不吃得下”,后者关心“网络扛不扛得住”。窗口也不是越大越好;过大的在途数据会增加缓存占用,丢包时也可能带来更多重传成本。

TCP 交付的是字节流,没有天然的“消息边界”。应用协议必须自己定义边界,例如 HTTP 使用首部与内容长度,其他协议可能使用换行符、固定长度或长度字段。一次 send 并不保证对应接收端的一次 recv

5. 连接关闭:FIN、半关闭与 RST

正常关闭通常被画成“四次挥手”:

TCP 是全双工的。一端发送 FIN,只表示自己不再发送数据,仍可以继续接收另一端尚未发完的数据,这就是半关闭。另一方向稍后也发送 FIN,双方分别确认。

“四次”是逻辑过程,不意味着抓包一定看到四个独立报文。若接收方恰好也准备关闭,它可能把 ACK 与自己的 FIN 合并发送。RST 则代表异常中止,例如目标端口没有监听、应用强制关闭,或协议栈判定连接不可继续。

6. 看懂常见 TCP 状态

状态 含义 排查提示
LISTEN 本地进程正在等待连接 确认监听地址与端口是否正确
SYN_SENT 已发 SYN,等待响应 检查路由、防火墙和目标端口
ESTABLISHED 连接已建立 不代表应用响应一定健康
CLOSE_WAIT 对端已关闭,本地应用尚未关闭 大量长期存在时重点检查应用是否释放连接
TIME_WAIT 主动关闭方暂时保留连接信息 用于处理迟到报文并保证最终 ACK 可重传,少量出现属正常现象

不要一看到 TIME_WAIT 就调低内核等待时间。应先判断连接创建频率是否异常、能否复用长连接,以及应用是否合理管理连接池。大量长期 CLOSE_WAIT 往往比 TIME_WAIT 更直接地指向应用层关闭逻辑。

7. TCP 与 UDP 怎么选

对比项 TCP UDP
连接 建立连接后传输 无连接数据报
交付抽象 有序字节流 保留数据报边界
可靠性 内置确认、重传、流量与拥塞控制 不内置可靠交付,应用按需实现
典型关注点 正确、完整、顺序 时延、简单、可定制
常见场景 Web、数据库连接、文件传输 DNS 查询、实时音视频、游戏状态更新

“实时业务一定用 UDP”也不准确。协议选择取决于是否允许丢失、是否需要顺序、网络环境与实现成本。QUIC 就运行在 UDP 之上,但在用户态重新实现了可靠传输、拥塞控制和加密握手等能力。

8. 一套由下到上的排障路径

排障时最好一次只验证一层,并记录“域名、IP、端口、时间点、错误信息”这五项上下文。

第一步:域名能否解析

1
Resolve-DnsName eulersail.com

也可以使用跨平台更常见的 nslookup eulersail.com。若解析失败,先检查 DNS 配置、记录是否生效以及本机缓存,不要急着怀疑 HTTP 服务。

第二步:目标端口能否建立 TCP 连接

1
Test-NetConnection eulersail.com -Port 443

如果 DNS 正常而端口不通,再检查本机路由、云防火墙、安全组、服务监听地址与端口。tracert eulersail.com 可以辅助观察路径,但中间节点不响应探测并不等于业务流量一定不通。

第三步:TLS 与 HTTP 是否正常

1
2
curl.exe -I https://eulersail.com/
curl.exe -v https://eulersail.com/

-I 适合快速查看状态码与响应头,-v 能展示 DNS、连接、TLS 和 HTTP 交互细节。不要为了“临时成功”长期关闭证书校验;证书错误应从域名匹配、有效期、系统时间和证书链入手。

第四步:查看本机连接状态

1
2
Get-NetTCPConnection | Sort-Object State
netstat -ano

端口与进程号只能说明“哪个进程占用连接”,还要结合应用日志、反向代理日志和同一时间点的请求 ID 判断根因。

9. 常见误区

  • Ping 不通就是网站故障:ICMP 可能被禁用,而 TCP 443 仍然正常。
  • TCP 建连成功就是接口正常:建连只验证到传输层,HTTP 仍可能超时或返回错误状态码。
  • 三次握手是为了交换三次数据:核心是双方确认收发能力并同步序列号。
  • 四次挥手永远对应四个包:ACK 与 FIN 可能合并,异常关闭还可能直接出现 RST。
  • OSI 每层都有独立软件模块:它首先是职责模型,实际实现可能跨层优化或合并。

10. 小结

理解网络时,可以始终追问四个问题:数据属于哪一层、这一层使用什么标识、它保证了什么、失败时怎样单独验证。沿着 DNS、路由、TCP、TLS、HTTP 逐层缩小范围,比记忆孤立术语更接近真实工程。

参考资料