1. 引言

计算机网络是每位计算机学者的必修课,也是各大厂面试中的重点考察内容。本文将从后端开发的角度,整理出高效的知识点。考虑到时间有限,本文将侧重于知识的性价比,建议有时间的同学更系统地学习。

我们以一个经典问题引入话题:当浏览器地址栏输入www.baidu.com时,发生了什么?

2. 重点知识

2.1. DNS解析

以首次访问为例,DNS解析涉及多个层次:浏览器缓存、系统缓存、Hosts文件、路由器缓存和递归DNS服务器。

浏览器缓存

每个浏览器都有自己的DNS缓存,记录常用域名与IP地址的对应关系(带有过期时间)。当浏览器缓存未命中时,它会查询系统缓存。如果你使用Chrome浏览器,可以在地址栏输入chrome://net-internals/#dns来查看当前的DNS缓存。
dns-1.png

系统缓存

浏览器会进行系统调用,查询RAM中的DNS缓存。你可以使用nslookup命令手动检查是否存在对应域名的缓存(适用于Linux和MacOS)。如果没有命中缓存,浏览器将继续查询Hosts文件。

dns-2.png

Hosts文件

Hosts文件包含用户手动配置的域名与IP的映射。在许多公司的内网中,常用来配置数据库、中间件或其他对IP敏感的服务的域名映射。你可以通过修改/etc/hosts文件来进行自定义配置。

dns-3.png

递归DNS服务器

如果Hosts文件未找到对应映射,浏览器会查询路由器缓存。如果路由器缓存也未命中,浏览器将递归查询本地DNS服务器。这个递归过程涉及根域名、顶级域名和权威域名的逐层查询。

dns-4.png

当本地DNS服务器无法找到目标域名(如baidu.com)时,查询将继续进行。这时,服务器会迭代地访问根域名服务器、顶级域名服务器和权威域名服务器,以获取对应的IP地址。具体而言,本地服务器首先向根域名服务器查询baidu.com,得到目标域名所在地区的顶级域名服务器的IP地址。然后,本地DNS服务器根据该IP地址访问顶级域名服务器,继续迭代,直到找到baidu.com的IP地址。

dns-5.png

为了更好地理解这一过程,我们可以在终端模拟本地DNS服务器迭代查询目标域名(例如bilibili.com)。使用dig命令进行DNS记录查询时,首先我们向根域名服务器找到了包含bilibili.com.com顶级域名服务器地址。接下来,我们可以使用任意一个顶级域名服务器的IP地址继续查询bilibili.com的IP地址。

dns-6.png

需要注意的是,实际操作中,当我执行dig命令时,本地DNS服务器通常会直接命中缓存,而无需再向根域名服务器进行查询,因此后续的查询过程不再演示。

2.2. ARP解析

ARP解析是在局域网内确定IP地址对应的MAC地址的过程,也涉及多个层次:本地ARP缓存、ARP请求和ARP应答。

本地ARP缓存

每台计算机都有自己的ARP缓存,用于存储已解析的IP地址与MAC地址的映射关系。当需要发送数据包到特定IP地址时,系统会首先检查本地ARP缓存。如果缓存中已有对应的MAC地址,则直接使用该地址进行数据传输。我们可以通过arp -a命令来查看当前系统的ARP缓存(适用于Linux和MacOS):

arp-1.png

执行命令 arp -a 显示了系统中的ARP缓存,下面是每一行的解释:

  • IP地址:每一行的第一个部分是IP地址,例如 192.168.115.1

  • MAC地址:紧随其后的是对应的MAC地址,例如 6c:92:bf:7f:29:f5

  • 接口on en0 表示该IP地址与 en0 接口(通常是以太网接口或无线网络接口)相关联。

  • ifscope:指示这个ARP条目是有效的,表示它是针对特定接口的。

  • 永久:有些条目(例如 mdns.mcast.net239.255.255.250)标记为“permanent”,表示这些条目是持久的,不会过期。

  • 广播地址192.168.115.255 对应的MAC地址是 ff:ff:ff:ff:ff:ff,这是一个广播地址,表示发送给网络中所有设备。

ARP请求

如果本地ARP缓存未命中,系统会发送ARP请求广播包,询问网络中“谁拥有这个IP地址?”该请求包会被网络中的所有设备接收。

arp-2.png

ARP应答

拥有该IP地址的设备收到ARP请求后,会发送ARP应答,包含其MAC地址。这个应答包是单播的,直接发回请求的设备。

更新ARP缓存

一旦接收到ARP应答,请求的设备将新的IP地址与MAC地址的映射关系存入本地ARP缓存,以便于后续请求时快速访问。

通过以上步骤,ARP解析能够有效地将目标IP地址转换为对应的MAC地址,以实现数据包在局域网中的正确传输。

2.3. 建立连接

一旦获取到IP地址,浏览器会通过该地址与目标服务器建立TCP连接,通常使用HTTP的默认端口80,或者HTTPS的端口443。这一过程被称为“TCP的三次握手”。

TCP报文

TCP是一种面向连接的可靠全双工通信协议,其报文头格式如下:

tcp-1.png

相关字段含义如下(每个字段都十分重要),这些字段总和为20字节,即TCP报文头的长度:

NameDescSize (bits)
Source Port源端口16
Destination Port目的端口16
Sequence Number序列号(seq),在TCP传输流中,每个字节按顺序编号。当SYN=1时即为初始序列号(ISN),否则为当前数据段的第一个字节的序列号。32
Acknowledgment Number确认号(ack),表示接收方期望收到下一个TCP报文段的第一个字节的序列号,通常为seq+132
Header Length首部长度,指数据部分起始处与TCP数据段起始处的字节偏移量,确定TCP数据段头部的长度。4
Reserved保留字段,当前必须全部为0。包含控制位:
- CWR:拥塞窗口减少
- ECE:ECN回显
- URG:紧急数据
- ACK:确认号有效
- PSH:立即推送数据
- RST:重置连接
- SYN:同步序号
- FIN:标记数据发送完毕
4
Window Size窗口大小,从Ack Number开始还能接收多少字节的数据,表示当前接收端的接收窗口剩余空间。16
TCP Checksum校验位,确认传输的数据是否损坏,发送端和接收端生成的值必须相同。计算基于伪头+TCP头+TCP数据。16
Urgent Pointer紧急指针,仅在URG控制位为1时有效,指出本数据段中紧急数据的字节数。16
Option可选项字段,长度不定,但长度必须是32 bits的整数倍。32X

三次握手

tcp-2.png

三次握手可以用打电话的场景来生动说明,假设甲要和乙通话:

:喂,听得到吗?
:听得到,你呢?
:我也听得到,咱们说正事。

开始时,双方都是CLOSED状态。甲作为客户端主动发起连接,乙作为服务端被动接收连接。服务端的TCP进程创建传输控制块(TCB),进入LISTEN监听状态。

第一次握手:客户端创建TCB,向服务端发送请求,报文头中的SYN=1,表示初始序列号seq=x,此时客户端进入SYN-SENT状态。

第二次握手:服务端收到请求后,如果同意连接,向客户端发送确认报文,包含ACK=1SYN=1,初始化序列号seq=y,并确认上一个报文ack=x+1,此时服务端进入SYN-RCVD状态。

第三次握手:客户端收到确认后,再次确认,报文中ACK=1,序列号seq=x+1,同时确认上一个报文ack=y+1,至此TCP连接建立,客户端进入ESTABLISHED状态。

为什么需要三次握手?第一次证明客户端发送能力正常,第二次确认服务端的发送和接收能力,第三次确保客户端接收能力正常。

如果只有两次握手,可能导致状态不一致。假设第一次握手后请求滞留在网络中,客户端未收到确认,可能重新发起连接。此时,服务端会建立两个连接,导致状态不对等。

三次握手可以有效抵御网络波动,确保连接的可靠性。

四次挥手

tcp-3.png

我们可以将这部分内容简化,使其更清晰和易于理解。以下是优化后的版本:

数据传输完毕后,双方可以释放连接。最开始,客户端和服务器都处于ESTABLISHED状态,客户端主动关闭,服务器被动关闭。

第一次挥手:客户端发出连接释放报文,停止发送数据。报文首部中FIN=1,序列号为seq=u(即最后一个传送字节的序号加1),此时客户端进入FIN-WAIT-1状态。

第二次挥手:服务端收到释放报文,发送确认报文,ACK=1ack=u+1,并带上自己的序列号seq=v,此时服务端进入CLOSE-WAIT状态。

第三次挥手:客户端接收到服务端的确认,发送FIN=1ACK=1的报文,序列号seq=w(通常是v+1),ack=u+1,客户端进入FIN-WAIT-2状态,等待服务器的释放报文。服务器发送完最后的数据后,发出连接释放报文,进入LAST-ACK状态,等待客户端确认。

第四次挥手:客户端收到服务端的释放报文后,发送确认ACK=1ack=w+1,序列号seq=u+1,此时进入TIME-WAIT状态。虽然连接尚未终止,但客户端需要等待2MSL(最大报文生存时间,通常为2分钟),直到撤销相应的TCB后,才会进入CLOSED状态。服务器在收到确认后立即进入CLOSED状态,TCP连接至此断开,四次挥手完成。

为什么客户端要等待2MSL?
这主要是为了确保最后发送的ACK报文能到达服务端。如果ACK报文丢失,服务端会在2MSL内重发第三次挥手,增加了容错性。

2.4. 优化技术

连续ARQ协议

TCP协议通过使用连续ARQ协议和滑动窗口协议来确保数据传输的可靠性。

ARQ(自动重传请求)是一种错误纠正协议,适用于OSI模型中的数据链路层和传输层。它通过确认和超时机制,在不可靠服务的基础上实现可靠传输。如果发送方在一定时间内未收到确认帧,通常会重新发送数据。ARQ协议包括停止等待ARQ和连续ARQ,具备错误检测、正面确认、超时重传和负面确认及重传等机制。

连续ARQ协议:为了提高信道利用率,连续ARQ协议允许发送方连续发送一组数据包,而无需在每个数据包后等待确认。这种方式称为流水线传输,发送方可以在未收到ACK时继续发送多个分组,提升了传输效率。

arq-1.png

滑动窗口

滑动窗口是一种流量控制技术,旨在提高网络通信的效率。早期网络中,发送方往往不知道网络拥堵情况,导致数据包在中间节点被阻塞和丢失。为了解决这个问题,滑动窗口应运而生。

滑动窗口允许发送方在接收方未确认之前,连续发送多个数据包。接收方会通过窗口尺寸字段(Window Size)告知发送方可以发送多少数据。

在TCP中,滑动窗口的大小表示接收方的缓冲区容量。发送方根据这个大小决定要发送多少字节的数据。当窗口为0时,发送方通常停止发送数据。滑动窗口还用于实现ACK确认、流量控制和拥塞控制等功能。

tcp-4.png

拥塞控制

拥塞控制的目标是确保数据传输速率与网络承载能力匹配,从而实现高效和公平的网络使用。拥塞控制算法主要分为四个阶段:

  1. 慢启动(Slow Start)

    • 连接开始时,TCP拥塞窗口(cwnd)从一个较小的值(通常是一个段的大小)开始。
    • 每收到一个确认(ACK),cwnd加倍,导致窗口大小快速增长。
    • 当cwnd达到阈值(ssthresh)时,转入拥塞避免阶段。
  2. 拥塞避免(Congestion Avoidance)

    • 在这一阶段,每经过一个往返时间(RTT),cwnd增加1个最大段大小(MSS)。
    • 这种增长速度较慢,有助于防止网络拥塞。
  3. 快重传和快恢复(Fast Retransmit and Fast Recovery)

    • 当接收方连续收到三个重复的ACK时,发送方会立即重传丢失的数据包,而不是等待重传计时器。
    • 快恢复算法会调整ssthresh的值,并将cwnd设置为ssthresh加上3个MSS的大小,然后进入拥塞避免阶段。

tcp-5.png

HTTP版本比较

HTTP(超文本传输协议)随着时间演变,版本间在性能和安全性上进行了多次改进。以下是HTTP 1.0、1.1、2.0和3.0的主要区别:

特性HTTP 1.0HTTP 1.1HTTP 2.0HTTP 3.0
连接非持久连接,每个请求后关闭TCP连接默认持久连接,减少连接开销使用二进制分帧,多路复用请求基于QUIC,减少连接建立时间
请求请求与响应独立,无优先级或多路复用支持请求管线化,在一个连接中发送多个请求同时发送多个请求,解决队头阻塞改进的拥塞控制和无缝迁移连接
头部头部信息重复发送,增加开销引入更多缓存控制头部,如Cache-Control头部压缩(HPACK),减少开销默认使用TLS 1.3进行加密,提高安全性
缓存缓存机制较弱,不支持ETag等头部增强的缓存机制提供更高效的缓存机制内置安全性
特点每个请求都需要建立新的连接允许多个请求在同一连接上进行提高了传输效率和资源利用率提升移动性,改进的拥塞控制

HTTPS原理

HTTPS(HTTP over SSL)是一种安全的传输协议,通过在HTTP上增加SSL/TLS层来保障数据的安全性。

特性SSLTLS
开发者Netscape公司IETF(互联网工程任务组)
首次发布1994年(SSLv2),1995年(SSLv3)1999年(TLS 1.0)
主要功能提供私密性、信息完整性和身份认证提供保密性和数据完整性
版本SSLv1(未发布)、SSLv2、SSLv3TLS 1.0、1.1、1.2、1.3
安全性安全性较弱,存在多个已知漏洞提升了安全性,修复了SSL中的一些漏洞

SSL(安全套接层)握手是客户端和服务器建立安全连接的过程,确保数据在传输过程中的保密性和完整性。以下是TLS/SSL握手的详细步骤:

ssl-1.png

  1. 客户端Hello

    • 客户端发送一个Hello消息,包含支持的TLS版本、加密套件列表和生成的随机数。
  2. 服务器Hello

    • 服务器回应一个Hello消息,选择一个TLS版本和加密套件,同时发送自己的随机数。
  3. 服务器证书

    • 服务器向客户端发送其数字证书,包含公钥和其他身份信息。
  4. 服务器密钥交换(可选):

    • 服务器可能发送一个密钥交换消息,用于协商密钥材料。
  5. 请求客户端证书(可选):

    • 服务器可以请求客户端提供证书以进行身份验证。
  6. 客户端证书(可选):

    • 如果请求,客户端发送其数字证书。
  7. 客户端密钥交换

    • 客户端生成预主密钥(pre-master secret),用服务器的公钥加密后发送给服务器。
  8. 生成会话密钥

    • 客户端和服务器使用预主密钥以及之前交换的随机数生成对称密钥(会话密钥)。
  9. 结束握手

    • 客户端发送Finished消息,表明握手结束,并开始加密数据传输。
    • 服务器也发送Finished消息,确认握手成功。
  10. 加密通信

    • 一旦握手完成,客户端和服务器开始使用会话密钥进行加密的双向通信。

SSL握手过程确保客户端和服务器之间建立安全连接。通过公钥加密和数字证书,保证了密钥交换的安全性和双方身份的验证。即使在不安全的网络环境中,这一过程也能有效保护通信的机密性和完整性。

常见状态码

状态码类别含义
100信息性状态码Continue:继续发送请求
101信息性状态码Switching Protocols:切换协议
200成功状态码OK:请求成功
201成功状态码Created:成功创建新资源
202成功状态码Accepted:请求已接受,尚未处理
204成功状态码No Content:请求成功,但无内容
301重定向状态码Moved Permanently:永久重定向
302重定向状态码Found:临时重定向
303重定向状态码See Other:在另一个URI找到响应
304重定向状态码Not Modified:未修改,可使用缓存版本
307重定向状态码Temporary Redirect:临时重定向
400客户端错误状态码Bad Request:请求格式错误
401客户端错误状态码Unauthorized:需要用户认证
403客户端错误状态码Forbidden:拒绝执行请求
404客户端错误状态码Not Found:资源不存在
405客户端错误状态码Method Not Allowed:不允许的方法
408客户端错误状态码Request Timeout:请求超时
500服务器错误状态码Internal Server Error:服务器内部错误
501服务器错误状态码Not Implemented:不支持请求的功能
502服务器错误状态码Bad Gateway:无效的响应
503服务器错误状态码Service Unavailable:服务器无法处理请求
504服务器错误状态码Gateway Timeout:网关未及时收到响应
505服务器错误状态码HTTP Version Not Supported:不支持的HTTP协议版本

3. 其他

3.1. 浏览器渲染

浏览器渲染页面的原理可以概括为以下几个主要步骤:

  1. 解析HTML构建DOM树:从服务器获取HTML后,解析并构建DOM(文档对象模型)树,反映页面结构。

  2. 解析CSS构建CSSOM树:解析CSS,构建CSSOM(CSS对象模型)树,包含所有样式规则。

  3. 构建渲染树:结合DOM树和CSSOM树,生成渲染树,只包含可见节点及其样式。

  4. 布局(Layout):计算渲染树中每个节点的确切位置和大小,进行重排(Reflow)。

  5. 绘制(Painting):根据布局信息将内容绘制到屏幕上,进行重绘(Repaint)。

  6. 合成(Compositing):将页面不同部分绘制到不同层上,然后合成显示,以提高渲染性能。

这个过程是逐步进行的,了解这些步骤可以帮助开发者优化网页性能。

循此苦旅,以达天际