计算机网络相关面试题

一、HTTP1.1和HTTP2的区别

HTTP/1(主要指 HTTP/1.1)和 HTTP/2 是 Web 协议发展中的两个重要版本,二者在性能、协议机制和功能特性上有显著差异。以下从多个维度对比分析,并结合具体案例说明:

一、连接与请求处理方式

1. HTTP/1.1:串行请求与队头阻塞
  • 特点

    • 虽支持持久连接(Keep-Alive),但同一 TCP 连接同一时刻只能处理一个请求,请求需按顺序排队执行。
    • 若某个请求阻塞(如响应慢或失败),会导致后续请求被阻塞,即队头阻塞(Head-of-Line Blocking)
  • 示例
    浏览器加载一个网页,包含:

    • 1 个 HTML 文件(主资源)
    • 3 张图片(image1.jpg、image2.jpg、image3.jpg)
    • 1 个 CSS 文件(style.css)
    • 1 个 JS 文件(script.js)

    在 HTTP/1.1 中,浏览器需逐个发起请求

    请求顺序:HTML → CSS → JS → image1 → image2 → image3  
    (每个请求需等待前一个响应完成,总耗时较长)
    
2. HTTP/2:多路复用(Multiplexing)
  • 特点
    • 同一 TCP 连接中可并行发送多个请求 / 响应,通过流(Stream)帧(Frame)机制区分不同请求。
    • 彻底解决队头阻塞问题,多个资源可同时传输,无需排队。
  • 示例
    同样加载上述网页,HTTP/2 中所有资源请求同时发起,浏览器通过唯一流ID标识每个请求(如:流 1=HTML,流 2=CSS,流 3=JS,流 4-6 = 图片)。
    服务器将响应数据拆分为二进制帧(如 HEADERS 帧、DATA 帧),混合传输后由客户端按流 ID 重组。
    总耗时大幅减少,尤其适合高延迟或带宽受限场景。

二、协议格式:文本 vs 二进制

1. HTTP/1.1:纯文本格式
  • 特点
    请求和响应头部、实体均为文本格式,可读性强但解析效率低,冗余量大。
    • 例如,每次请求需重复传输相同头部字段(如Host: example.com)。
2. HTTP/2:二进制分帧(Binary Framing)
  • 特点
    • 将整个请求 / 响应分解为最小单位的(如 HEADERS 帧、DATA 帧、SETTINGS 帧等),以二进制格式传输。
    • 解析速度更快,且帧结构可精确控制(如标记流优先级、结束流等)。
  • 示例
    一个 HTTP/2 请求的 HEADERS 帧包含压缩后的头部数据,DATA 帧包含实体内容。客户端收到混合的帧后,按流 ID 合并为完整的请求 / 响应。
    对比:HTTP/1.1 的文本格式需逐行解析,而 HTTP/2 的二进制格式可通过位运算快速处理,提升性能。

三、头部压缩机制

1. HTTP/1.1:无头部压缩
  • 问题
    每次请求 / 响应的头部字段重复传输(如AcceptUser-AgentCookie等),尤其在移动端或低带宽场景下浪费流量。
2. HTTP/2:HPACK 压缩算法
  • 机制
    • 客户端和服务器维护一个共享的头部字段缓存表(Header Table),首次请求时传输完整头部,后续重复字段通过索引引用缓存表。
    • 对未缓存的字段采用哈夫曼编码压缩。
  • 示例
    首次请求https://example.com/page1时,头部包含:
    GET /page1 HTTP/2  
    Host: example.com  
    User-Agent: Chrome/115...  
    
    第二次请求/page2时,HostUser-Agent字段可直接引用缓存表中的索引,仅传输变化的字段(如GET /page2)。
    效果:头部体积可压缩至原大小的 10%~20%,节省带宽。

四、服务器推送(Server Push)

1. HTTP/1.1:无此功能

客户端需主动发起所有资源请求,服务器无法主动推送资源。

2. HTTP/2:主动推送关联资源
  • 机制
    服务器可根据客户端请求,主动推送其可能需要的资源(如 CSS、JS、图片等),避免客户端二次请求。
  • 示例
    客户端请求index.html,服务器解析 HTML 后发现需加载style.cssmain.js,可通过Link头或 API 主动推送这两个文件:
    <!-- HTML中声明推送资源 -->
    <link rel="preload" href="style.css" as="style" />
    <link rel="preload" href="main.js" as="script" />
    
    效果:客户端无需额外请求style.cssmain.js,直接从服务器缓存中获取,减少 RTT(往返时间)。

五、优先级与流量控制

1. HTTP/1.1:无显式优先级

资源按请求顺序处理,无法指定优先级(如先加载 CSS 再加载图片)。

2. HTTP/2:流优先级(Stream Priority)
  • 机制
    客户端可通过:priority头部为每个流设置优先级(如权重、依赖关系),服务器根据优先级分配资源(如先处理 CSS 流,再处理图片流)。
  • 示例
    加载网页时,CSS 样式表的优先级高于图片,客户端可声明:
    :method: GET  
    :path: /style.css  
    :priority: weight=200, depend=0  # 权重200,无依赖流  
    
    服务器优先处理该流,确保 CSS 先加载,避免页面渲染阻塞。

六、性能对比总结

特性HTTP/1.1HTTP/2
连接方式单连接串行请求单连接多路复用
协议格式文本格式二进制分帧
头部压缩HPACK 算法
服务器推送不支持支持
队头阻塞存在消除
典型页面加载耗时1000ms(假设)300ms(假设,多路复用 + 压缩)

二、 TCP的重传机制

一、TCP 可靠传输的基础:序列号与确认应答(ACK)

  1. 序列号(Sequence Number)

    • 每个 TCP 报文段的数据部分会被分配一个序列号,用于标识数据在字节流中的位置(如首字节序号)。
    • 作用:确保接收方按顺序重组数据,检测重复或丢失的报文段。
  2. 确认应答(ACK)

    • 接收方收到报文段后,会向发送方返回 ACK,其中包含 “期望接收的下一个字节的序号”(即确认号)。
    • 示例:若接收方成功收到序号为 x、长度为 L 的数据,则 ACK 的确认号为 x+L,表示 “已收到 x 到 x+L-1 的数据,期望接收 x+L 开始的数据”。

二、重传机制的触发条件

当发送方发现数据未被正确确认时,会触发重传。常见触发场景包括:

 
  1. 超时未收到 ACK(超时重传)

    • 发送方为每个报文段设置 重传超时时间(RTO,Retransmission Timeout)
    • 若超过 RTO 未收到对应 ACK,则认为报文段丢失,触发重传。
  2. 收到重复 ACK(快速重传)

    • 当接收方发现中间某个报文段丢失时,后续收到的报文段会触发重复 ACK(即连续发送多个相同的确认号)。
    • 发送方若收到 3 个重复 ACK(即 “累计 3 次确认号未更新”),则认为该报文段丢失,立即重传(无需等待超时),以降低延迟。

三、重传策略详解

1. 超时重传(Timeout Retransmission)

  • 核心逻辑

    • 发送方发送数据后启动定时器,若超时未收到 ACK,则重传该数据。
    • 首次 RTO 通常设为 初始值(如 3 秒),后续根据网络情况动态调整。
  • RTO 的动态计算

    • 通过 往返时间(RTT,Round-Trip Time) 测量网络延迟,公式如下:
      • 平滑往返时间(SRTT):SRTT = (1 - α) * SRTT + α * RTT(α 通常为 0.125)。
      • 偏差值(RTTVAR):RTTVAR = (1 - β) * RTTVAR + β * |RTT - SRTT|(β 通常为 0.25)。
      • RTO:RTO = SRTT + δ * RTTVAR(δ 通常为 2)。
    • Karn 算法:重传时不更新 RTT,避免因重传报文段的 ACK 无法区分原始 / 重传报文,导致 RTT 测量误差。
  • 缺点

    • 超时时间较长时,重传延迟高;
    • 网络波动可能导致 RTO 调整不及时。
2. 快速重传(Fast Retransmission)

  • 核心逻辑

    • 当接收方发现数据失序时,会针对已接收的后续数据连续发送重复 ACK(确认号为失序报文段的起始序号)。
    • 发送方收到 3 个重复 ACK 后,立即重传丢失的报文段,无需等待超时。
    • 示例
      • 发送方按顺序发送报文段 1、2、3、4,若报文段 2 丢失:
        • 接收方收到 1 后,ACK 确认号为 2;
        • 收到 3 后,因 2 未到,再次 ACK 确认号为 2(重复 ACK);
        • 收到 4 后,继续 ACK 确认号为 2(累计 3 次重复 ACK);
        • 发送方触发快速重传,立即重传报文段 2。
  • 优点

    • 相比超时重传,能更快检测到丢失,减少延迟。
3. 选择性重传(Selective Retransmission,SACK)

  • 背景

    • 传统重传机制会重传 整个窗口内未确认的数据(如超时重传),即使只有部分数据丢失,导致效率低下。
    • 选择性确认(SACK,Selective Acknowledgment) 是 TCP 的扩展选项,允许接收方告知发送方 哪些数据已正确接收,哪些数据丢失,从而仅重传丢失的部分。
  • 实现方式

    • 接收方在 ACK 中通过 SACK 选项 携带多个连续字节块的范围(如 “已收到 1-1000 和 2001-3000”)。
    • 发送方根据 SACK 信息,仅重传未被确认的字节块,避免重传已接收的数据。
  • 前提

    • 需要双方在 TCP 连接建立时协商启用 SACK 选项(通过 SYN 报文段携带)。

四、重传次数限制与资源释放

  • 重传次数上限

    • 为避免无限重传消耗资源,TCP 会限制最大重传次数(如 Linux 默认值为 15 次,对应 RTO 从初始值指数级增长到约 30 分钟)。
    • 超过上限后,TCP 会断开连接并通知应用层。
  • 与拥塞控制的协同

    • 重传机制与拥塞控制紧密关联:
      • 超时重传通常触发 拥塞避免(Congestion Avoidance) 或 慢启动(Slow Start) 机制,降低发送速率以缓解网络拥堵;
      • 快速重传后通常进入 快恢复(Fast Recovery) 阶段,在不降低拥塞窗口的前提下调整发送策略。

三、TCP的拥塞控制

TCP 的拥塞控制是通过动态调整发送端的 拥塞窗口(Congestion Window, cwnd) 来实现的,目的是避免网络过载导致的丢包和性能下降。其核心机制包括以下四种算法的协同工作:慢启动(Slow Start)拥塞避免(Congestion Avoidance)快重传(Fast Retransmit) 和 快恢复(Fast Recovery)。以下是详细解析:

一、核心概念

  1. 拥塞窗口(cwnd)
    发送端维护的一个状态变量,表示当前网络允许发送端发送的数据量上限(单位为「报文段个数」)。

    • 发送端实际的发送窗口大小 = min (cwnd, 接收端通告的窗口大小)。
    • cwnd 会根据网络拥塞情况动态调整。
  2. 慢启动阈值(ssthresh)
    区分「慢启动阶段」和「拥塞避免阶段」的阈值:

    • 当 cwnd < ssthresh 时,处于慢启动阶段;
    • 当 cwnd ≥ ssthresh 时,进入拥塞避免阶段。

二、四大拥塞控制算法

1. 慢启动(Slow Start)
  • 目标:初始阶段快速探测网络可用带宽,避免突发流量拥塞。
  • 规则
    • 初始时,cwnd = 1(单位为 MSS,最大段大小)。
    • 每收到一个确认(ACK),cwnd += 1每经过一个往返时间(RTT),cwnd 呈指数增长(如 1→2→4→8→…)。
  • 触发条件
    • 新连接建立时;
    • 超时重传后(进入慢启动阶段)。
  • 阈值调整
    • 当 cwnd 增长到等于 ssthresh 时,切换至「拥塞避免阶段」。
    • 若中途检测到拥塞(如超时),执行:
      ssthresh = max(cwnd/2, 2)(取半,最小为 2),cwnd = 1,重新进入慢启动。
2. 拥塞避免(Congestion Avoidance)
  • 目标:避免网络拥塞,使 cwnd 线性增长,稳定传输。
  • 规则
    • 每经过一个 RTT,cwnd += 1(线性增长,而非指数)。
  • 触发条件
    • cwnd ≥ ssthresh 时自动进入。
  • 阈值调整(拥塞发生时)
    • 若检测到超时(严重拥塞):
      ssthresh = cwnd/2cwnd = 1,回到慢启动阶段。
    • 若检测到「三个重复 ACK」(轻度拥塞,见快重传):
      执行快重传 + 快恢复算法(见下文)。
3. 快重传(Fast Retransmit)
  • 目标:尽早检测到单个报文段丢失,避免不必要的超时等待。
  • 触发条件
    • 接收端收到失序报文段时,重复发送前一个正确报文段的 ACK。
    • 当发送端收到 3 个重复 ACK 时,判定为「丢包」,立即重传丢失的报文段,无需等待超时。
  • 操作
    • 重传丢失的报文段;
    • 进入「快恢复阶段」,不执行慢启动。
4. 快恢复(Fast Recovery)
  • 目标:在轻度拥塞(三个重复 ACK)时,快速恢复传输,避免过度降低 cwnd。
  • 规则
    1. ssthresh = cwnd/2(设置新的阈值);
    2. cwnd = ssthresh + 3(假设丢失的报文段已被接收端缓存,允许发送 3 个新报文段);
    3. 每收到一个重复 ACK,cwnd += 1(线性增加,快速恢复);
    4. 当收到丢失报文段的 ACK 时,cwnd = ssthresh,进入「拥塞避免阶段」。
  • 与慢启动的区别
    • 不将 cwnd 重置为 1,而是基于当前阈值快速恢复,减少吞吐量波动。

三、关键对比

场景处理方式cwnd 调整ssthresh 调整
新连接 / 超时重传慢启动重置为 1设为 cwnd/2
三个重复 ACK快重传 + 快恢复设为 ssthresh + 3设为 cwnd/2
拥塞避免阶段正常传输线性增长 cwndcwnd += 1(每 RTT)不变

 四、TCP的流量控制

TCP 的流量控制(Flow Control)是通过 滑动窗口机制(Sliding Window) 实现的,主要用于解决 发送方发送速率过快,导致接收方处理不及而丢包 的问题。其核心思想是:接收方根据自身接收能力,动态通知发送方调整发送窗口大小,从而控制数据传输速率。以下是详细解析:

一、核心机制:滑动窗口(Sliding Window)

1. 基本概念
  • 接收窗口(Receiver Window, rwnd)
    接收方在 ACK 报文 中通告给发送方的 可用接收缓冲区大小,表示接收方当前能接收的数据量。
    • 单位:字节(Byte)。
    • 范围:0 ≤ rwnd ≤ 接收缓冲区大小
  • 发送窗口(Send Window, swnd)
    发送方根据接收方通告的 rwnd 维护的 允许发送的数据范围,实际大小由 rwnd 决定(可能受拥塞窗口限制,此处先不考虑拥塞控制)。
2. 窗口滑动过程

发送方维护以下四个指针(以字节为单位)

[已发送并确认] <--- [已发送未确认] <--- [未发送但可发送] <--- [未发送且不可发送]^左边界          ^右边界          ^发送窗口右边界        ^数据末尾
  • 已发送并确认:数据已被接收方确认,可从缓冲区删除。
  • 已发送未确认:数据已发送但未收到确认,处于窗口内。
  • 未发送但可发送:未超出发送窗口,可直接发送。
  • 未发送且不可发送:超出发送窗口,需等待窗口滑动后才能发送。

窗口滑动条件

  • 当 已发送未确认的数据被确认 时,左边界右移,窗口滑动,释放空间允许发送新数据。
  • 当 接收方通告新的 rwnd 时,右边界可能扩大或缩小,调整发送窗口大小。

二、流量控制的具体实现

1. 接收方通告窗口大小(Window Advertisement)
  • 接收方在 ACK 报文 的 窗口字段(Window Field) 中告诉发送方当前可用的接收缓冲区大小(rwnd)。
  • 发送方根据 rwnd 更新发送窗口 swnd,公式为:
    swnd = min(rwnd, 拥塞窗口 cwnd)
    (此处先忽略拥塞窗口 cwnd,假设仅受流量控制影响,则 swnd = rwnd)。
2. 动态调整窗口大小
  • 窗口扩大:接收方处理完数据,释放接收缓冲区后,通过增大 rwnd 通知发送方可以发送更多数据。
  • 窗口缩小:接收方缓冲区快满时,通过减小 rwnd 通知发送方降低发送速率。
  • 零窗口(Zero Window):当接收缓冲区已满时,接收方将 rwnd 设为 0,发送方停止发送数据,进入 窗口关闭状态
3. 零窗口与窗口探测(Zero Window Probe)
  • 问题:当接收方通告 rwnd=0 后,发送方停止发送数据。若接收方后续释放了缓冲区,但未及时通知发送方,会导致双方僵持(死锁)。
  • 解决方案
    • 发送方启动 零窗口定时器(Zero Window Timer),超时后发送一个 探测报文段(仅含 1 字节数据),询问接收方当前 rwnd
    • 接收方收到探测报文后,回复新的 rwnd,若仍为 0,则重新开启定时器;若 rwnd>0,则发送方恢复数据发送。

三、流量控制与拥塞控制的区别

维度流量控制拥塞控制
目标防止接收方缓冲区溢出(点对点控制)防止网络拥塞(全局网络负载控制)
控制方接收方(通过 rwnd 通告)发送方(根据网络状态动态调整)
机制滑动窗口(基于接收方能力)慢启动、拥塞避免、快重传、快恢复等
作用范围发送方与接收方之间所有网络主机(端到端)

四、示例:流量控制过程

  1. 初始状态

    • 接收方缓冲区大小为 1000 字节,初始 rwnd=1000,发送方 swnd=1000,发送 500 字节数据。
    • 此时,接收方缓冲区剩余 500 字节,回复 ACK 并通告 rwnd=500,发送方将 swnd 调整为 500
  2. 窗口缩小

    • 接收方处理缓慢,缓冲区剩余 200 字节,回复 ACK 并通告 rwnd=200,发送方 swnd 调整为 200,仅允许发送 200 字节新数据。
  3. 零窗口

    • 接收方缓冲区满,通告 rwnd=0,发送方停止发送,启动零窗口定时器。
    • 定时器超时后,发送方发送探测报文,接收方处理数据后释放缓冲区,通告 rwnd=300,发送方恢复发送。

五、TCP 连接建立、状态管理及销毁的完整过程

         在 TCP 连接建立过程中,当客户端发起第一次握手,SYN 包到达服务器时,服务器会创建 TCB(TCP Control Block)并将该连接放入半连接队列(SYN 队列)。此时,连接处于未完全建立状态。待客户端发送 ACK 完成第三次握手,服务器会把连接从半连接队列移至全连接队列(accept 队列),同时将 TCB 标记为 ESTABLISHED 状态,意味着连接已成功建立。这里需要注意,连接进入全连接队列时状态就已变为 ESTABLISHED,而非在 accept () 调用之后。accept () 函数的作用是从全连接队列中取出连接,将 TCB 与应用层 socket 关联,分配 fd 和文件结构体,把已建立的连接交付给应用层。即使应用程序未调用 accept (),全连接队列中的连接依然维持 ESTABLISHED 状态,直到队列满时会触发 SYN 重传或拒绝新连接。在 Linux 系统中,半连接队列和全连接队列的大小可分别通过 net.ipv4.tcp_max_syn_backlog 和 somaxconn 参数进行配置。当连接断开,如完成四次挥手,主动关闭方会进入 TIME_WAIT 状态,此时 TCB 不会立即销毁,而是会保留一段时间(默认 60 秒,可配置),以避免旧数据包对新连接造成干扰。

六、TCP连接状态如何变化

TCP 连接管理通过有限状态机(FSM)实现,共有11 种状态,涵盖连接建立、数据传输、连接关闭的完整生命周期。以下是各状态的详细说明及状态转换流程:

一、TCP 连接的 11 种状态

1. CLOSED(关闭状态)
  • 描述:虚拟初始状态,表示无连接或连接已关闭。
  • 转换
    • 客户端主动发起连接时,从CLOSEDSYN_SENT
    • 服务端被动监听时,从CLOSEDLISTEN
2. LISTEN(监听状态)
  • 描述:服务端等待客户端连接请求。
  • 触发条件:服务端调用listen()后进入此状态。
  • 转换
    • 收到客户端SYN包,发送SYN+ACKSYN_RCVD
    • 主动关闭连接→CLOSED
3. SYN_SENT(同步已发送状态)
  • 描述:客户端已发送SYN包,等待服务端确认。
  • 触发条件:客户端调用connect()后发送SYN
  • 转换
    • 收到服务端SYN+ACKESTABLISHED(三次握手完成)。
    • 超时未收到回复→重发SYN,若多次失败→CLOSED
4. SYN_RCVD(同步已接收状态)
  • 描述:服务端已收到客户端SYN,并回复SYN+ACK,等待客户端确认。
  • 触发条件:服务端收到SYN后发送SYN+ACK
  • 转换
    • 收到客户端ACKESTABLISHED
    • 超时未收到ACK→重发SYN+ACK,失败则→CLOSED
5. ESTABLISHED(已建立连接状态)
  • 描述:连接已建立,双方可双向传输数据。
  • 触发条件:三次握手完成(客户端和服务端均进入此状态)。
  • 转换
    • 主动关闭连接(发送FIN)→FIN_WAIT_1(客户端)或CLOSE_WAIT(服务端)。
    • 被动关闭连接(收到对方FIN)→CLOSE_WAIT(客户端)或LAST_ACK(服务端)。
6. FIN_WAIT_1(终止等待 1 状态)
  • 描述:主动关闭方(如客户端)已发送FIN,等待对方确认。
  • 触发条件:主动关闭方调用close()shutdown()发送FIN
  • 转换
    • 收到对方ACKFIN_WAIT_2
    • 收到对方FIN+ACK→直接处理FINTIME_WAIT(跳过FIN_WAIT_2)。
7. FIN_WAIT_2(终止等待 2 状态)
  • 描述:主动关闭方已收到对方ACK,等待对方发送FIN
  • 触发条件:从FIN_WAIT_1收到ACK后进入。
  • 转换
    • 收到对方FIN→发送ACKTIME_WAIT
    • 对方长期不关闭→可能保持此状态直到超时(需系统配置支持)。
8. CLOSE_WAIT(关闭等待状态)
  • 描述:被动关闭方(如服务端)收到FIN,但尚未发送自身FIN,需处理剩余数据。
  • 触发条件:被动关闭方收到FIN后回复ACK,进入此状态。
  • 转换
    • 处理完数据后,主动发送FINLAST_ACK
    • 若直接关闭(未发送FIN)→可能导致连接泄漏,需程序主动调用close()
9. LAST_ACK(最后确认状态)
  • 描述:被动关闭方已发送FIN,等待主动关闭方的ACK
  • 触发条件:被动关闭方发送FIN后进入此状态。
  • 转换
    • 收到ACKCLOSED
    • 超时未收到ACK→重发FIN,失败则→CLOSED
10. TIME_WAIT(时间等待状态)
  • 描述:主动关闭方在发送ACK后等待一段时间(2 倍 MSL),确保连接安全关闭。
  • 触发条件:主动关闭方在FIN_WAIT_2收到FIN并回复ACK后进入。
  • 作用
    • 防止最后一个ACK丢失,导致对方重发FIN时可重新响应。
    • 避免旧连接的数据包混入新连接(MSL 为最大段生存时间)。
  • 转换
    • 等待超时(2MSL)→CLOSED
    • 收到重发的FIN→重新回复ACK并重置超时。
11. CLOSING(关闭中间状态)
  • 描述:罕见状态,双方同时主动关闭时可能出现(双方同时发送FIN)。
  • 触发条件:双方同时从ESTABLISHED发送FIN,各自进入FIN_WAIT_1,收到对方FIN后→CLOSING
  • 转换
    • 发送ACK并收到对方ACKTIME_WAIT

七、TCP如何保证可靠传输的

TCP(传输控制协议)通过多种机制确保数据的可靠传输,核心思路是确认应答、重传机制、流量控制、拥塞控制、顺序控制等。以下是具体实现方式:

1. 序列号(Sequence Number)与确认应答(ACK)

作用
  • 唯一标识数据字节:每个字节的数据都有唯一的序列号(32 位),用于标记数据顺序,解决网络中数据乱序问题。
  • 确认应答机制:接收方收到数据后,通过确认号(ACK Number)告知发送方已成功接收的数据的下一个字节的序列号,表示该序列号之前的数据均已正确接收。
示例
  • 发送方发送序列号为 1000、长度为 200 的数据(即字节范围 1000~1199),接收方收到后,返回 ACK=1200,表示 1200 之前的数据(1000~1199)已确认接收。
  • 发送方通过未确认的序列号判断哪些数据需要重传。

2. 重传机制(Retransmission)

作用
  • 当数据丢失或确认超时,发送方重新传输数据,确保数据最终到达。
实现方式
  1. 超时重传(Timeout Retransmission)

    • 发送方发送数据时启动定时器,若超时未收到对应 ACK,则重传数据。
    • 定时器初始值由 RTT(往返时间) 估算得出,超时时间会动态调整(如 Karn 算法 避免重传时的 RTT 计算误差)。
  2. 快速重传(Fast Retransmission)

    • 接收方发现数据失序时,立即发送重复确认(Dup ACK)(指向最后一个正确接收的连续序列号)。
    • 发送方若收到 3 个相同的 Dup ACK,判断为数据包丢失,立即重传对应的数据包,无需等待超时(减少延迟)。

3. 流量控制(Flow Control)

作用
  • 通过 ** 滑动窗口(Sliding Window)** 机制,让发送方的发送速率匹配接收方的处理能力,避免接收方缓冲区溢出。
实现方式
  • 接收窗口(rwnd):接收方在 ACK 中携带自己当前的接收缓冲区剩余大小(即允许发送方发送的数据量)。
  • 发送方根据 rwnd 调整发送窗口,确保发送的数据不超过接收方的处理能力。
  • 若 rwnd=0,发送方暂停发送,直到接收方通过 ACK 通知窗口更新(如 TCP Keepalive 机制防止死锁)。

4. 拥塞控制(Congestion Control)

作用
  • 避免网络中数据流量过大导致拥塞(如路由器队列溢出、丢包率上升),实现全局网络稳定性。
核心算法
  1. 慢启动(Slow Start)

    • 初始时,发送方以 **1 个 MSS(最大段大小)** 为窗口大小,每收到一次 ACK 就将窗口大小翻倍(指数增长),快速探测网络容量。
    • 当窗口大小超过慢启动阈值(ssthresh)时,进入拥塞避免阶段
  2. 拥塞避免(Congestion Avoidance)

    • 窗口大小线性增长(每轮往返时间增加 1 个 MSS),避免网络过载。
    • 若检测到丢包(如超时或 3 次 Dup ACK),触发拥塞处理
  3. 快重传(Fast Retransmit)与快恢复(Fast Recovery)

    • 若通过 3 次 Dup ACK 检测到丢包,执行快重传,并将 ssthresh 设为当前窗口的一半,进入快恢复阶段(窗口大小线性减少,而非重置为 1),继续线性增长以快速恢复传输。
    • 若通过超时检测到丢包,视为严重拥塞,ssthresh 设为当前窗口的一半,窗口重置为 1,重新进入慢启动。

5. 校验和(Checksum)

  • 作用:检测数据在传输过程中是否损坏或篡改。
  • 实现方式:发送方在头部计算伪首部 + 数据的校验和,接收方进行校验。若校验失败,直接丢弃数据包,不返回 ACK,触发发送方重传。

6. 顺序控制与重复数据删除

  • 顺序控制:接收方通过序列号对数据排序,将失序的数据暂存于缓冲区,等待缺失的数据包到达后按顺序交付应用层。
  • 重复数据删除:若收到重复序列号的数据包,直接丢弃并返回相同的 ACK,避免重复处理。

7. 连接管理(三次握手与四次挥手)

  • 三次握手:确保双方初始序列号同步,建立可靠连接,避免历史连接干扰。
  • 四次挥手:确保双方数据完全传输完毕后断开连接,释放资源(如 TIME_WAIT 状态防止最后一个 ACK 丢失导致的连接异常)。

总结:可靠传输的核心机制

机制作用描述
序列号 / 确认号标记数据顺序,确认应答确保数据到达
重传机制超时重传和快速重传处理丢包
流量控制端到端控制发送速率,避免接收方缓冲区溢出
拥塞控制全局控制发送速率,避免网络拥塞
校验和检测数据损坏,丢弃错误包
顺序与重复控制排序数据、去重,确保按序交付
连接管理可靠建立和释放连接,同步状态

八、DNS域名解析的过程

DNS(域名系统)域名解析是将人类易读的域名(如www.example.com)转换为计算机可识别的 IP 地址的过程。这一过程涉及多级域名服务器的协同工作,通常分为递归查询迭代查询两个阶段。以下是详细解析过程:

一、初始请求:客户端发起查询

  1. 本地缓存检查
    当用户在浏览器输入域名(如www.baidu.com)时,操作系统会首先检查本地 DNS 缓存(包括浏览器缓存、系统缓存)。若缓存中有该域名对应的 IP 地址,直接返回结果,解析过程结束。

    • 浏览器缓存:浏览器会存储近期解析过的域名记录(存活时间由 DNS 响应中的 TTL 字段决定)。
    • 系统缓存:操作系统(如 Windows 的nscd、Linux 的systemd-resolved)也会缓存 DNS 结果,减少重复查询。
  2. 本地 DNS 服务器(递归解析器)
    若本地缓存中无记录,客户端会向本地 DNS 服务器(通常由 ISP 提供,或手动设置为公共 DNS 如 114.114.114.114)发送递归查询请求

    • 递归查询的特点:本地 DNS 服务器需负责全程查询,直到返回最终结果或失败。

二、递归查询:本地 DNS 服务器的迭代查询过程

本地 DNS 服务器若未缓存目标域名,需通过迭代查询向上级域名服务器逐步获取信息,流程如下:

1. 根域名服务器(Root DNS Server)

本地 DNS 服务器首先向根域名服务器发起查询。根服务器负责管理顶级域名(如.com、.cn 等)的解析权,返回对应 ** 顶级域名服务器(TLD Server)** 的地址。

 
  • 根服务器全球共 13 组(A~M),通过任播技术分布在全球各地。
  • 示例:查询www.baidu.com时,根服务器会返回.com顶级域名服务器的地址。
2. 顶级域名服务器(TLD Server)

本地 DNS 服务器根据根服务器返回的地址,向 **.com顶级域名服务器查询。TLD 服务器负责管理该顶级域名下的所有二级域名(如baidu.com),返回对应权威域名服务器(Authoritative Server)** 的地址。

 
  • 示例:.com TLD 服务器会返回baidu.com的权威服务器地址(如ns1.baidu.com)。
3. 权威域名服务器(Authoritative Server)

本地 DNS 服务器向权威域名服务器发起最终查询。权威服务器是域名所有者配置的服务器,存储该域名的具体解析记录(如 A 记录、AAAA 记录),直接返回域名对应的 IP 地址。

 
  • 示例:baidu.com的权威服务器会返回www.baidu.com的 IP 地址(如 14.215.177.38)。

三、结果返回与缓存

  1. 响应回传
    权威服务器将 IP 地址返回给本地 DNS 服务器,后者再将结果回传给客户端。客户端收到 IP 地址后,即可与目标服务器建立连接(如 HTTP 请求)。

  2. 缓存记录

    • 本地 DNS 服务器会缓存解析结果,供后续其他客户端查询使用。
    • 客户端也会将结果存入本地缓存,缓存时间由 DNS 响应中的TTL(生存时间)字段控制(如 TTL=3600 秒表示缓存 1 小时)。

关键概念补充

  1. 递归查询 vs. 迭代查询

    • 递归查询:客户端只需向本地 DNS 服务器发起一次请求,服务器全程负责查询(“代劳到底”)。
    • 迭代查询:本地 DNS 服务器逐次向根→TLD→权威服务器查询,每次获取下一步地址(“逐步问路”)。
  2. DNS 协议细节

    • 使用UDP 协议(端口 53),因查询数据量小,UDP 效率更高;若响应超时,可能 fallback 到 TCP。
    • 支持DNSSEC(域名系统安全扩展),通过数字签名防止 DNS 欺骗(DNS 污染)。
  3. 现代扩展技术

    • DNS over HTTPS(DoH)/ DNS over TLS(DoT):加密 DNS 查询,避免中间人攻击,常用于浏览器(如 Chrome、Firefox)。
    • 任播(Anycast):根服务器和部分公共 DNS 通过任播技术,让客户端就近连接最近的节点,提升响应速度。

九、生动讲解HTTPS加密过程

我们以「用户访问招商银行官网(cmbchina.com)并登录」为例,全程模拟 HTTPS 加密过程,每个步骤都对应具体的操作和数据,让你像看电影一样理解整个流程:

场景设定

  • :坐在电脑前的用户,打开浏览器输入 https://cmbchina.com
  • 招商银行服务器:真正的银行服务器,持有合法数字证书
  • 黑客小明:躲在中间试图窃听或篡改通信(假设存在,但最终失败)

一、客户端发起连接:你「敲门」问安全能力(TLS 握手第 1 步)

你的浏览器动作

 
  1. 发送一个「Hello 请求」给招商银行服务器,内容包括:
    • 随机数 A:20250521_abc123(好比你随手写的一串乱码)
    • 支持的加密算法:[ECDHE-RSA-AES256-GCM-SHA384, RSA-AES256-CBC-SHA]
    • TLS 版本:TLS 1.3(最新安全版本)
      类比:你隔着门喊:“我带了 AES256 和 RSA 两种密码本,用 TLS 1.3 协议聊,这是我的乱码片段 A!”
 

黑客小明的动作:试图拦截这个请求,但此时还没加密,内容可见,但他不知道接下来会发生什么。

二、服务器验证身份:银行「出示身份证」(TLS 握手第 2-3 步)

招商银行服务器动作

  1. 回复「Hello 响应」,内容包括:

    • 选择加密算法:ECDHE-RSA-AES256-GCM-SHA384(选了你支持的最强算法)
    • 随机数 B:server_20250521_def456(服务器的乱码片段)
    • 数字证书
      • 证书内容:
        • 域名:cmbchina.com(必须和你访问的域名一致)
        • 公钥:-----BEGIN PUBLIC KEY-----...(服务器的公钥,用于加密数据)
        • 有效期:2024.01.01 - 2026.12.31(未过期)
        • CA 签名:由 DigiCert(知名 CA 机构)用私钥签名的哈希值
      • 比喻:服务器递给你一张 “身份证”,上面有银行照片(域名)、有效期、公安局盖章(CA 签名)。
  2. 你验证证书真伪(浏览器自动完成):

    • 检查域名:确认证书里的域名是cmbchina.com,不是cmbchina-fake.com
    • 检查有效期:当前时间是 2025 年 5 月,证书未过期。
    • 用 DigiCert 的公钥(浏览器内置根 CA 公钥)解密证书中的「数字签名」,对比证书内容的哈希值是否一致(确保证书没被篡改)。
      如果证书有问题:比如黑客伪造了一个cmbchina.com的证书,但没有 DigiCert 的私钥,签名验证失败,浏览器会弹出 “不安全” 警告。

黑客小明的动作

  • 想冒充银行服务器,伪造了一个证书,但签名无法通过 CA 验证,你根本不会信任他。
  • 或直接拦截服务器的真实证书,替换成自己的假证书,但你的浏览器发现签名不对,拒绝继续通信。

三、密钥交换:生成「只有你和银行知道的密码本」(TLS 握手第 4-5 步)

你的浏览器动作

  1. 生成「预主密钥」:pre_master_key_xyz789(真正的密码本核心)。
  2. 用招商银行证书中的公钥加密预主密钥,发送给服务器:公钥加密(pre_master_key_xyz789)
    比喻:你用银行身份证上的公钥(公开的锁)把密码本核心锁在盒子里,只有银行的私钥(唯一的钥匙)能打开。

招商银行服务器动作

  1. 用自己的私钥解密收到的密文,得到预主密钥:pre_master_key_xyz789
  2. 双方独立计算「会话密钥」:
    • 公式:会话密钥 = 哈希(预主密钥 + 随机数A + 随机数B)
    • 结果:双方得到相同的对称密钥,比如session_key_secure123(用于后续加密的密码本)。
      比喻:你用A片段+预主密钥拼出密码本,银行用B片段+预主密钥拼出同样的密码本,黑客即使知道 A 和 B,但没有预主密钥(被公钥加密保护),无法算出会话密钥。

黑客小明的动作

  • 截获了随机数 A、B 和加密后的预主密钥,但没有银行私钥,无法解密预主密钥,更算不出会话密钥。

四、安全通信:用密码本加密传输登录数据(TLS 握手完成后)

你发送登录请求(假设账号user123,密码pass456):

  1. 浏览器用「会话密钥」加密数据:
    • 明文:{"username":"user123", "password":"pass456", "action":"login"}
    • 密文:AES256-GCM加密(session_key_secure123, 明文)(变成乱码)
  2. 发送密文给银行服务器。

招商银行服务器接收并解密

  1. 用「会话密钥」解密密文,得到明文:user123pass456
  2. 验证登录信息正确后,返回加密的账户余额:
    • 明文:{"balance":"100000元", "timestamp":"2025-05-21 14:30"}
    • 密文:AES256-GCM加密(session_key_secure123, 明文)

黑客小明的动作

  • 截获了密文,但没有会话密钥,无法解密,看到的只是乱码:�N�w���S�C�...
  • 想篡改密文中的 “balance” 为 “1000000 元”,但篡改后密文的完整性校验(GCM 模式带认证)会失败,服务器会丢弃该数据。

五、关键细节:如果中间人参战会怎样?

假设黑客小明成功冒充路由器,实施中间人攻击

  1. 伪造证书:小明生成一个假的cmbchina.com证书(自签名证书,无 CA 签名)。

    • 你的浏览器验证时发现证书签名无效,弹出警告:“该网站证书不可信!”
    • 你选择 “继续访问”(危险操作),此时进入 “不安全通道”,小明可窃取密钥。
  2. 成功欺骗的极端情况

    • 小明是某机构员工,持有伪造的 CA 证书(现实中几乎不可能,因根 CA 私钥极难窃取)。
    • 你的浏览器信任该 CA,认为证书有效,此时小明可充当 “中间人”,解密你和银行的通信(这就是为什么根 CA 安全至关重要)。

总结:例子中的核心对应关系

HTTPS 流程具体例子场景安全作用
数字证书招商银行的 “官方身份证”防止冒充,验证身份
公钥加密预主密钥用银行公钥锁密码本核心确保密钥传输安全
会话密钥你和银行的共享密码本高效加密大量数据
对称加密通信加密传输登录密码和账户余额防止窃听和篡改

十、浏览器从输入url到展示页面,经历了哪些过程

一、导航准备阶段:处理 URL & 安全校验

场景:你在地址栏输入zhihu.com并按回车

  1. URL 标准化

    • 浏览器自动补全协议:http:// → https://(若默认启用 HTTPS)
    • 修正格式:去除多余空格,处理特殊字符(如%20转空格)
    • 示例:输入zhihu.com → 转为https://www.zhihu.com/(可能带默认路径)
  2. 安全检查(关键!)

    • 协议校验
      • http: 直接跳转,https: 需走加密流程(触发 TLS 握手)
    • 跨站脚本防护(XSS)
      • 检查 URL 是否包含恶意脚本(如javascript:alert(1)),拦截危险内容
    • 浏览器安全策略
      • 遵循Content Security Policy (CSP)头(若有),限制资源加载来源

二、DNS 解析:从域名到 IP 的「地址翻译」

场景:需要知道www.zhihu.com的服务器 IP

  1. 多级缓存查询(速度优先)

    • 浏览器缓存:先查本地缓存(如 Chrome 输入chrome://net-internals/#dns可看),若有 IP(有效期内)直接使用
    • 系统缓存:查本机hosts文件(Windows 在C:\Windows\System32\drivers\etc\hosts),可手动绑定 IP
    • 路由器缓存:家用路由器可能缓存 DNS 记录,减少重复查询
  2. 递归查询流程(若缓存失效)

    • 本地 DNS 服务器(LDNS)
      你的网络服务商提供的 DNS(如电信 / 联通的 DNS),先查其缓存,若没有则:
    • 根 DNS 服务器:返回.com顶级域服务器地址(如a.gtld-servers.net
    • 顶级域(TLD)服务器:返回zhihu.com的权威 DNS 服务器地址
    • 权威 DNS 服务器:返回www.zhihu.com的真实 IP(如180.163.151.35
    • 耗时:全程约 50-200ms,HTTPS 站点可能用DNS-over-HTTPS (DoH)加密查询,防中间人攻击

三、网络连接:建立安全通道(TCP+TLS)

场景:与知乎服务器180.163.151.35:443建立连接

1. TCP 三次握手(可靠传输)
  • 你→服务器:发送 SYN 包,请求建立连接( seq=1001 )
  • 服务器→你:回复 SYN+ACK 包( seq=2001, ack=1002 )
  • 你→服务器:发送 ACK 包( ack=2002 ),连接建立
  • 关键点:确认双方收发能力正常,避免旧连接干扰
2. TLS 握手(HTTPS 加密通道)
  • 你发送 ClientHello
    支持的 TLS 版本(如 1.3)、加密算法列表(如 ECDHE-RSA-AES256-GCM)、随机数 A
  • 服务器返回 ServerHello + 证书
    选定算法、服务器数字证书(含公钥)、随机数 B
  • 你验证证书
    检查域名(www.zhihu.com)、有效期、CA 签名(内置根证书验证),若证书无效则弹窗警告
  • 生成会话密钥
    你用服务器公钥加密「预主密钥」发送,双方用预主密钥 + 随机数 A/B 算出相同的对称密钥(如session_key_secure
  • 耗时:约 1-RTT(往返时间),现代浏览器支持「TLS 会话复用」减少后续连接耗时

四、HTTP 请求与响应:获取页面原始数据

场景:向知乎服务器请求首页 HTML

  1. 发送请求(Request)

    • 请求行GET / HTTP/2(使用 HTTP/2 协议,多路复用)
    • 请求头
      {  "Host": "www.zhihu.com",  "User-Agent": "Mozilla/5.0 Chrome/115...", // 标识浏览器  "Accept": "text/html", // 声明接受HTML格式  "Cookie": "session_id=abc123" // 携带登录状态  
      }  
      
    • 请求体:GET 方法无,POST/PUT 等方法携带数据
  2. 服务器处理请求

    • 解析请求头,验证 Cookie(若已登录,返回个性化页面)
    • 生成响应内容:读取 HTML 文件、查询数据库(如用户信息、推荐内容)
    • 添加响应头:
      {  "Content-Type": "text/html; charset=utf-8", // 声明内容类型  "Cache-Control": "max-age=3600", // 浏览器缓存策略  "Set-Cookie": "new_session=xyz789" // 可能更新Cookie  
      }  
      
  3. 返回响应(Response)

    • 状态码200 OK(成功)、302 Found(临时重定向)、404 Not Found
    • 响应体:HTML 文本(如知乎首页的<html><head>...</head><body>...</body></html>
    • 耗时:取决于服务器处理速度、网络延迟,通常几十到几百毫秒

五、浏览器解析渲染:从代码到像素

场景:将知乎 HTML 转换为屏幕上的文字、图片、按钮

1. 构建渲染树(Render Tree)
  • 解析 HTML→DOM 树
    逐行解析 HTML,生成节点对象(如<div class="header">),形成树状结构
    • 遇到<script src="main.js">:暂停解析,下载 JS 并执行(默认阻塞渲染)
    • 遇到<link rel="stylesheet" href="style.css">:并行下载 CSS,不阻塞 HTML 解析
  • 解析 CSS→CSSOM 树
    解析 CSS 规则,生成样式对象(如.header { color: #333; }
  • 合并为渲染树
    过滤不可见元素(如display: none),保留需显示的节点(如visibility: hidden仍保留)
2. 布局计算(Layout)
  • 计算每个元素的几何属性:
    • 位置:基于 Flex/Grid 布局、盒模型(margin/padding/border)
    • 尺寸:宽高(如.header宽 100%,高 80px)
  • 示例:知乎首页头部导航栏,通过 CSS 计算得出左对齐、高度 60px、内边距 10px
3. 绘制(Paint)
  • 将元素的视觉属性(颜色、阴影、边框)转换为像素数据:
    • 文字渲染:调用系统字体引擎,生成字形像素
    • 图片解码:将下载的 JPEG/PNG 转为位图(可能触发「图片解码阻塞渲染」)
  • 优化点:浏览器将不同层级元素(如浮层、视频)分到不同图层,避免重复绘制
4. 合成(Composite)
  • 将多个图层按层级合并(如背景层→内容层→浮层),输出到屏幕:
    • 使用 GPU 加速合成(transform/opacity动画不会触发重排重绘)
    • 回流(Reflow):若修改布局(如width: 50%),需重新计算布局→绘制→合成
    • 重绘(Repaint):仅修改样式(如color: red),只需重新绘制→合成

六、资源加载与优化:并行获取图片、JS、CSS

场景:知乎首页 HTML 中引用了 LOGO 图片、JS 交互脚本、CSS 样式表

  1. 优先级与并行加载

    • 关键资源:CSS(阻塞渲染)、JS(阻塞解析,除非标记async/defer
    • 非关键资源:图片、字体、视频(异步加载)
    • 浏览器策略
      • 同一域名下最多建立 6-8 个 TCP 连接(HTTP/1.1),HTTP/2 支持多路复用(单个连接并发加载)
      • 预加载提示:HTML 中<link rel="preload" href="main.js">告知浏览器提前下载
  2. 示例资源加载流程

    • HTML 解析到<img src="logo.png">:发起 GET 请求获取图片(并行于 DOM 解析)
    • 解析到<script src="analytics.js" defer>:下载 JS 但不阻塞渲染,DOM 构建完成后执行
    • CSS 文件下载完成后,触发「样式重新计算」,可能导致部分元素重新布局

七、JS 执行:动态交互的核心

场景:知乎首页的搜索框自动补全、按钮点击事件

  1. 引擎编译执行

    • V8 引擎(Chrome)将 JS 代码编译为机器码:
      • 解析阶段:生成抽象语法树(AST)
      • 优化阶段:JIT(即时编译)优化热点代码(如循环)
    • 事件循环(Event Loop):处理异步操作(如setTimeout、AJAX 回调),避免阻塞主线程
  2. DOM 操作与性能影响

    • 示例代码:
      // 点击按钮修改文本(触发重绘)  
      document.getElementById('button').addEventListener('click', () => {  document.getElementById('text').style.color = 'red'; // 重绘  
      });  
      // 调整布局(触发回流+重绘)  
      document.getElementById('box').style.width = '200px';  
      
    • 优化建议
      • 批量修改 DOM(如先改display: none,改完再显示)
      • 使用requestAnimationFrame处理动画

八、收尾阶段:页面完成与后续处理

  1. onLoad 事件触发

    • 所有资源(HTML/CSS/JS/ 图片)加载完成后,执行window.onload回调
    • 示例:知乎首页在此阶段初始化全页面 JS 组件(如评论区、推荐算法)
  2. 浏览器优化机制

    • 预渲染:推测用户可能访问的链接(如鼠标悬停),提前加载页面内容
    • 内存管理:垃圾回收机制清理无效变量,避免内存泄漏

十一、HTTP协议中的cookie和session的区别

一、核心定义

1. Cookie
  • 本质:存储在客户端(浏览器 / 手机)本地小型文本数据(键值对形式)。
  • 作用:用于服务器识别用户身份,实现会话状态的持久化(如保持登录状态)。
  • 工作原理
    • 服务器通过响应头(Set-Cookie)向客户端发送 Cookie。
    • 客户端后续请求时,会自动在请求头(Cookie)中携带该 Cookie,回传给服务器。

例子
用户登录网站后,服务器返回一个包含user_id=123的 Cookie,客户端保存后,下次访问时自动携带该 Cookie,服务器通过user_id识别用户已登录。

2. Session
  • 本质:存储在服务器端会话数据(如用户权限、购物车信息等)。
  • 作用:用于记录用户在一次会话中的动态状态(如登录状态、临时数据)。
  • 工作原理
    • 服务器创建 Session 时,生成一个唯一的Session ID(如session_id=abc123)。
    • 通过 Cookie 将 Session ID 发送给客户端,客户端后续请求携带该 ID,服务器通过 ID 查找对应的 Session 数据。

例子
用户在电商网站添加商品到购物车,服务器创建一个 Session 存储购物车内容,并返回session_id给客户端。用户浏览其他页面时,携带session_id,服务器根据 ID 找到对应的购物车数据。

二、关键区别对比

维度CookieSession
存储位置客户端(浏览器、本地文件)服务器端(内存、数据库、文件系统等)
安全性较低(数据明文存储于客户端,易被篡改或窃取)较高(敏感数据存储在服务器,客户端仅存 Session ID)
数据容量小(单个 Cookie 通常限制为4KB,浏览器对每个域名的 Cookie 数量有限制)大(取决于服务器配置,可存储复杂数据结构)
有效期可设置(ExpiresMax-Age,支持持久化)默认仅在浏览器会话期间有效(关闭浏览器即过期),也可设置持久化
跨域支持同源策略限制(只能在同域名下使用)依赖 Cookie 传递 Session ID,因此同样受同源策略限制
服务器压力无(数据存储在客户端)有(每个用户会话占用服务器资源)
典型用途存储非敏感信息(如用户偏好、登录令牌)存储敏感或动态信息(如登录状态、购物车、表单临时数据)

三、典型应用场景

场景 1:用户登录状态保持
  • Cookie 方案
    服务器验证用户密码后,返回一个包含auth_token的 Cookie(设置有效期为 7 天)。用户下次访问时,浏览器自动携带该 Cookie,服务器验证令牌有效则允许登录。
    风险:若 Cookie 被窃取,攻击者可伪造身份(需配合HttpOnlySecure属性增强安全性)。

  • Session 方案
    服务器验证用户密码后,创建 Session 存储用户信息(如user_role=admin),并返回session_id的 Cookie。用户后续请求携带session_id,服务器通过 ID 查找 Session 并验证权限。
    优势:敏感信息(如user_role)不暴露在客户端,安全性更高。

场景 2:电商购物车
  • Cookie 方案
    将购物车商品 ID 存储在 Cookie 中(如cart=item1,item2)。
    缺点:数据容量有限,且用户在不同设备登录时无法同步购物车。

  • Session 方案
    购物车数据存储在服务器 Session 中,客户端仅存储session_id。用户更换设备后,重新登录即可同步购物车(需结合用户账号体系)。
    优势:支持大容量数据,跨设备同步方便。

四、配合使用:Cookie + Session

实际开发中,两者常结合使用:

  1. 服务器创建 Session,生成session_id
  2. 通过 Cookie 将session_id返回给客户端(这是 Session 机制的核心)。
  3. 客户端后续请求携带session_id,服务器通过 ID 识别用户会话。

优点

  • 利用 Cookie 的跨请求传递能力,避免每次请求都重新认证。
  • 敏感数据存储在服务器,降低客户端安全风险。

五、面试高频问题

  1. 为什么 Session 需要依赖 Cookie?
    答:Session 通过session_id识别用户会话,而session_id需要通过 Cookie 传递给客户端。若客户端禁用 Cookie,则需通过 URL 重写(如http://example.com/?session_id=abc123)传递,但安全性和兼容性较差。

  2. Cookie 的HttpOnlySecure属性有什么用?

    • HttpOnly:禁止 JavaScript 读取 Cookie(防止 XSS 攻击窃取 Cookie)。
    • Secure:仅在 HTTPS 连接下发送 Cookie(防止明文传输被劫持)。
  3. 分布式系统中如何管理 Session?
    答:单机 Session 无法跨服务器共享,需使用分布式 Session 方案(如 Redis 集群存储 Session 数据,所有服务器共享同一存储)。

十二、http和grpc的区别

一、核心定义与设计目标

1. HTTP
  • 本质:基于请求 - 响应模型应用层协议,用于规范客户端(如浏览器)与服务器之间的通信。
  • 设计目标
    • 实现超文本(文本、图片、视频等)的传输与展示,是 Web 服务的基础。
    • 强调通用性和可读性,支持跨平台、跨语言的交互(如浏览器可访问任何支持 HTTP 的服务器)。
 

典型场景

 
  • 浏览器访问网页(如 GET https://example.com/index.html)。
  • 对外提供 RESTful API(如调用第三方天气接口 GET https://api.weather.com/city=上海)。
2. RPC(Remote Procedure Call)
  • 本质:一种进程间通信机制,允许程序像调用本地函数一样调用远程服务器的函数。
  • 设计目标
    • 隐藏网络通信细节(如序列化、传输、反序列化),让开发者专注于业务逻辑。
    • 追求高效性和强类型约束,适用于分布式系统内部服务间的高频交互。
 

典型场景

 
  • 微服务架构中,用户服务调用订单服务的接口(如 userService.createOrder(userId, productId))。
  • 高性能场景下的内部通信(如电商系统中库存服务与支付服务的实时交互)。

二、关键区别对比

维度HTTPRPC
通信模型严格的请求 - 响应模型(一问一答)支持请求 - 响应、单向调用(如通知)、流式传输(如 gRPC 的双向流)
协议层级应用层协议(基于 TCP/IP)通常基于 TCP 或 HTTP/2,可自定义传输层协议
数据格式文本格式(JSON/XML),可读性强但体积较大二进制格式(如 Protobuf/Thrift),体积小、解析快
接口定义松散(通过 URL 和 HTTP 方法定义接口,如 GET /users/{id}强类型(通过 IDL(接口定义语言)明确接口参数和返回值,如 .proto 文件)
调用方式显式(需手动构造请求 URL、参数、 headers)隐式(自动生成客户端 Stub,像调用本地函数)
性能相对较低(文本解析、协议开销较大)较高(二进制协议、连接复用、更少网络开销)
跨语言支持天然跨语言(基于标准协议)依赖框架支持(需为每种语言生成对应 Stub)
服务治理需依赖外部组件(如 API 网关、Nginx)内置支持(如负载均衡、服务发现、熔断限流)

三、核心机制对比

1. 数据格式与序列化
  • HTTP
    以 JSON 为例,请求体可能是:

    {"method": "getUser","params": { "userId": "123" }
    }
    

    优点:易读、易调试,适合对外接口或需要人工介入的场景(如前端调试)。
    缺点:文本格式冗余,解析性能较低(如 JSON 转对象需遍历键值对)。

  • RPC
    以 Protobuf 为例,通过 .proto 文件定义接口:

    service UserService {rpc getUser(GetUserRequest) returns (UserResponse) {}
    }
    message GetUserRequest { string userId = 1; }
    

    编译后生成二进制数据(如 userId=123 可能编码为 0x0A\x03\x31\x32\x33)。
    优点:二进制格式紧凑(体积通常比 JSON 小 30%~50%),解析速度快(基于字段编号而非字符串匹配)。
    缺点:可读性差,需依赖工具生成代码。

2. 调用方式对比
  • HTTP 调用(以 RESTful 为例)
    客户端需手动构造 HTTP 请求,例如用 Python 的 requests 库:

    import requests
    response = requests.get("https://api.example.com/users/123", headers={"Authorization": "Bearer token"})
    data = response.json()
    

    特点:需显式处理网络请求细节(URL、headers、错误处理)。

  • RPC 调用(以 gRPC 为例)
    客户端通过自动生成的 Stub 调用,例如:

    import user_service_pb2_grpc, user_service_pb2channel = grpc.insecure_channel("order-service:50051")
    stub = user_service_pb2_grpc.UserServiceStub(channel)
    request = user_service_pb2.GetUserRequest(userId="123")
    response = stub.getUser(request)  # 像调用本地函数一样
    

    特点:网络通信细节(序列化、传输、反序列化)由框架自动处理,代码更简洁。

四、适用场景对比

适合用 HTTP 的场景
  1. 对外提供开放接口
    如第三方开发者调用的 API(如微信支付接口),需跨语言、跨平台兼容,HTTP+JSON 的组合简单易用。
  2. 需要浏览器直接访问的场景
    浏览器原生支持 HTTP,无需额外客户端库(如前端通过 fetch 调用接口)。
  3. 低性能要求的简单场景
    如内部管理系统的 API,对速度要求不高,但需要易调试和维护。
适合用 RPC 的场景
  1. 微服务架构内部通信
    如电商系统中,用户服务、订单服务、库存服务之间的高频交互,需高性能和强类型接口(如库存扣减时要求参数必须为整数)。
  2. 实时性要求高的场景
    如即时通讯、实时数据同步(如股票行情推送),RPC 的二进制协议和连接复用(如 HTTP/2 的多路复用)可减少延迟。
  3. 需要服务治理的复杂系统
    RPC 框架(如 Dubbo、gRPC)内置负载均衡、熔断、限流等功能,适合大规模分布式系统。

五、典型框架对比

类型框架 / 工具特点
HTTPFlask/Django快速开发 Web 服务,适合中小型项目。
HTTPSpring Boot基于 Java,支持 RESTful API,适合企业级应用。
RPCgRPC基于 HTTP/2,支持多语言,性能高,Google 开源(如用于 Kubernetes 内部通信)。
RPCDubbo阿里巴巴开源,支持丰富的服务治理功能,适合 Java 生态的微服务架构。
RPCThrift/Protobuf专注于序列化和接口定义,可独立于传输层使用(如通过 TCP 直接传输)。

六、面试高频问题

  1. 为什么 RPC 比 HTTP 快?
    答:

    • RPC 使用二进制协议(如 Protobuf),体积更小、解析更快;
    • 通常复用长连接(如 HTTP/2 的持久连接),减少 TCP 三次握手开销;
    • 框架层优化(如连接池、批量请求)进一步提升性能。
  2. HTTP 和 RPC 可以共存吗?
    答:可以。例如:

    • 对外提供 HTTP API 供浏览器 / 第三方调用;
    • 内部微服务之间使用 RPC 通信以提升性能(如电商平台的前端用 HTTP 调用网关,网关内部通过 RPC 调用各个服务)。
  3. gRPC 是 HTTP 还是 RPC?
    答:gRPC 是基于 HTTP/2 的 RPC 框架。它复用了 HTTP/2 的多路复用、二进制分帧等特性,但通过 IDL 实现了强类型的 RPC 调用,属于 RPC 范畴。

十三、HTTP方法GET、POST、PUT和PATCH的区别是什么

一、核心功能对比

方法功能描述
GET请求获取资源(如查询数据、获取文件等),不改变服务器状态
POST用于创建新资源(如提交表单、上传文件等),通常会导致服务器状态变化。
PUT更新资源(覆盖式更新),需指定完整资源数据,常用于替换已有资源或创建指定 ID 的资源。
PATCH部分更新资源,只需提交需要修改的字段,无需提供完整数据,比 PUT 更灵活高效。

二、关键特性对比

1. 幂等性(Idempotence)
  • 幂等性:多次执行相同操作,结果与一次执行相同,不会产生副作用。
    • GET:幂等。多次获取同一资源,结果不变(如查询商品列表)。
    • POST非幂等。多次提交可能创建多个资源(如重复提交订单)。
    • PUT:幂等。多次覆盖同一资源,结果一致(如用 PUT 更新用户信息,每次传入完整数据)。
    • PATCH非幂等。多次部分更新可能产生累积效果(如先修改用户邮箱,再修改手机号)。
2. 安全性(Safety)
  • 安全性:方法是否仅用于获取资源,不修改状态。
    • GET:安全。仅用于读取数据,不影响服务器状态。
    • POST/PUT/PATCH非安全。会修改服务器资源(如创建、更新数据)。
3. 参数位置
  • GET:参数通过 URL 传递(如 ?key=value),明文可见,长度受限(浏览器 / 服务器限制)。
  • POST/PUT/PATCH:参数通常放在请求体(Request Body)中,可传输较大数据,且不暴露在 URL 中。
4. 资源定位
  • GET/POST:资源由 URL 定位(如 GET /users 获取用户列表,POST /users 创建用户)。
  • PUT/PATCH:需指定具体资源的完整 URL(如 PUT /users/123 更新 ID 为 123 的用户)。

三、典型使用场景

1. GET
  • 查询数据:如获取用户信息、商品详情(GET /users/1)。
  • 非敏感数据请求:如获取静态文件(图片、API 列表)。
2. POST
  • 创建资源:如用户注册(POST /users 提交用户数据)、提交表单。
  • 非幂等操作:如支付请求(重复提交会导致多笔交易)。
3. PUT
  • 完整更新资源:如修改用户全部信息(需传入完整用户数据)。
  • 创建指定资源:如上传文件到固定路径(PUT /files/abc.txt)。
4. PATCH
  • 部分更新资源:如仅修改用户邮箱(PATCH /users/1 传入 {"email": "new@example.com"})。
  • 高效更新:避免传输未修改的字段,减少数据量(如 RESTful API 中优化更新操作)。

四、对比总结表格

特性GETPOSTPUTPATCH
用途读取资源创建资源全量更新部分更新
幂等性✅ 幂等❌ 非幂等✅ 幂等❌ 非幂等
安全性✅ 安全❌ 非安全❌ 非安全❌ 非安全
参数位置URL请求体请求体请求体
典型场景查询列表提交表单替换资源修改字段

五、常见误区与最佳实践

  1. 不要滥用 POST
    传统 Web 开发中常用 POST 处理所有操作,但在 RESTful 设计中,应根据操作类型选择方法(如更新用 PUT/PATCH,删除用 DELETE)。

  2. PUT vs. PATCH 的选择

    • 需要覆盖整个资源时用 PUT(如重置用户密码)。
    • 只需修改部分字段时用 PATCH(如更新用户头像 URL)。
  3. 幂等性的重要性
    在分布式系统中,幂等性可避免重复请求导致的数据不一致(如接口重试时,PUT 比 POST 更安全)。

0voice · GitHub  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/906474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图论算法精解(Java 实现):从基础到高频面试题

一、图的基础表示方法 1.1 邻接矩阵&#xff08;Adjacency Matrix&#xff09; 邻接矩阵是表示图的一种直观方式&#xff0c;它使用一个二维数组来存储节点之间的连接关系。对于一个有 n 个节点的图&#xff0c;邻接矩阵是一个 nn 的矩阵&#xff0c;其中 matrix [i][j] 表示…

江科大TIM定时器hal库实现

定时器相关hal库函数 hal库的定时器函数相比于标准库&#xff0c;多了很多的中断回调函数&#xff0c;同时对于定时器的初始化也改成使用句柄一次性顺带连带DMA等功能一起初始化了 typedef struct {uint32_t Prescaler; /*定时器的预分频值*/uint32_t CounterMode; …

CentOS 10:启动telnet服务

参考&#xff0c; 鳥哥私房菜 - 第七章、網路安全與主機基本防護&#xff1a;限制埠口, 網路升級與 SELinux 7.3.3 埠口与服务的启动/关闭及开机时状态设定 我们知道系统的 Telnet 服务通常是以 super daemon 来控管的&#xff0c;请您启动您系统的 telnet 试看看。 1 要启动 …

Taro 安全区域

目录 一、问题描述 二、问题解决 1、顶部刘海区 2、底部小黑条 一、问题描述 安全区域主要是为了避免刘海屏或底部栏遮挡&#xff0c;而造成的不良显示效果。 本次将针对以下两点进行考量&#xff1a; 1、顶部刘海屏区 2、苹果X底部小黑条 二、问题解决 通过Taro.getS…

【Java微服务组件】分布式协调P1-数据共享中心简单设计与实现

欢迎来到啾啾的博客&#x1f431;。 记录学习点滴。分享工作思考和实用技巧&#xff0c;偶尔也分享一些杂谈&#x1f4ac;。 欢迎评论交流&#xff0c;感谢您的阅读&#x1f604;。 目录 引言设计一个共享数据中心选择数据模型键值对设计 数据可靠性设计持久化快照 &#xff08…

在SpringBoot项目中,使用单元测试@Test

1.引入依赖 <!--单元测试Test的依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>3.2.1</version> </dependency> 2.在src/test/java目录…

在Java中,将Object对象转换为具体实体类对象

在Java中&#xff0c;将Object对象转换为具体实体类对象可以通过以下几种方法实现&#xff1a; 1‌.使用instanceof关键字进行类型检查和转换‌&#xff1a; 首先&#xff0c;使用instanceof关键字检查Object对象是否为目标实体类的类型。 如果是&#xff0c;则进行强制类型…

JAVA学习-练习试用Java实现“音频文件的读取与写入 :使用Java音频库处理音频数据”

问题&#xff1a; java语言编辑&#xff0c;实现音频文件的读取与写入 &#xff1a;使用Java音频库处理音频数据。 解答思路&#xff1a; 在Java中处理音频文件通常需要使用第三方库&#xff0c;例如javax.sound.sampled包&#xff0c;它提供了处理音频文件的基本功能。以下是一…

Flink架构概览,Flink DataStream API 的使用,FlinkCDC的使用

一、Flink与其他组件的协同 Flink 是一个分布式、高性能、始终可用、准确一次&#xff08;Exactly-Once&#xff09;语义的流处理引擎&#xff0c;广泛应用于大数据实时处理场景中。它与 Hadoop 生态系统中的组件可以深度集成&#xff0c;形成完整的大数据处理链路。下面我们从…

linux 查看java的安装路径

一、验证Java安装状态 java -version正常安装会显示版本信息&#xff1a; openjdk version "1.8.0_65" OpenJDK Runtime Environment (build 1.8.0_65-b17) OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode)二、检查环境变量配置 若已配置JAVA_HOME&#…

2025-5-21 个人笔记篇matlab小笔记和clang基础使用(简单记录)

个人笔记篇 再不记录就找不到了&#xff0c;之前学的一点基础&#xff0c;看看就行,请不要提问,因为很久了>_<(至少我看来是这样的) matlab小笔记 % 开绘制(新建) figure % 设置绘制标题 title(标题); % 设置绘制的X轴Lable xlabel(x); % 设置绘制的y轴Lable ylabel(cos…

前端JavaScript-嵌套事件

点击 如果在多层嵌套中&#xff0c;对每层都设置事件监视器&#xff0c;试试看 <!DOCTYPE html> <html lang"cn"> <body><div id"container"><button>点我&#xff01;</button></div><pre id"output…

网感驱动下开源AI大模型AI智能名片S2B2C商城小程序源码的实践路径研究

摘要&#xff1a;在数字化浪潮中&#xff0c;网感已成为内容创作者与商业运营者必备的核心能力。本文以开源AI大模型、AI智能名片及S2B2C商城小程序源码为技术载体&#xff0c;通过解析网感培养与用户需求洞察的内在关联&#xff0c;提出"数据驱动-场景适配-价值重构"…

AG-UI:重构AI代理与前端交互的下一代协议标准

目录 技术演进背景与核心价值协议架构与技术原理深度解析核心功能与标准化事件体系典型应用场景与实战案例开发者生态与集成指南行业影响与未来展望1. 技术演进背景与核心价值 1.1 AI交互的三大痛点 当前AI应用生态面临三大核心挑战: 交互碎片化:LangGraph、CrewAI等框架各…

游戏引擎学习第301天:使用精灵边界进行排序

回顾并为今天的内容做准备 昨天&#xff0c;我们解决了一些关于排序的问题&#xff0c;这对我们清理长期存在的Z轴排序问题很有帮助。这个问题我们一直想在开始常规游戏代码之前解决。虽然不确定是否完全解决了问题&#xff0c;但我们提出了一个看起来合理的排序标准。 有两点…

Ajax快速入门教程

输入java时&#xff0c;页面并没有刷新但是下面自动联想出了跟java有关的东西&#xff0c;像这种就叫异步交互 它不会妨碍你的输入&#xff0c;同时还能够同步进行对于java相关联想词的推送 发送异步请求需要借助工具axios 引入axios&#xff0c;可以直接在scripts中引入 get和…

Anti Spy安卓版:智能防护,守护手机安全

Anti Spy安卓版是一款专为安卓设备设计的智能防护应用&#xff0c;旨在帮助用户实时防护手机安全&#xff0c;抵御间谍软件、恶意软件和其他潜在威胁。它基于人工智能和启发式搜索方法的引擎&#xff0c;能够检测并阻止已知和未知的间谍软件、后门程序、账单欺诈、短信欺诈、电…

超低延迟音视频直播技术的未来发展与创新

引言 音视频直播技术正在深刻改变着我们的生活和工作方式&#xff0c;尤其是在教育、医疗、安防、娱乐等行业。无论是全球性的体育赛事、远程医疗、在线教育&#xff0c;还是智慧安防、智能家居等应用场景&#xff0c;都离不开音视频技术的支持。为了应对越来越高的需求&#x…

系统架构设计(十二):统一过程模型(RUP)

简介 RUP 是由 IBM Rational 公司提出的一种 面向对象的软件工程过程模型&#xff0c;以 UML 为建模语言&#xff0c;是一种 以用例为驱动、以架构为中心、迭代式、增量开发的过程模型。 三大特征 特征说明以用例为驱动&#xff08;Use Case Driven&#xff09;需求分析和测…

海康相机连接测试-极简版

文章目录 1、下载客户端 1、下载客户端 海康机器人官网下载软件 软件下载地址 先下载客户端测试连接 按照你的相机的类型选择客户端 安装完毕后&#xff0c;确保USB线插的是3.0的端口 软件会自动识别相机型号 在上方有播放按钮&#xff0c;可以采集图像信息显示