4.计算机网络
4.1 简述静态路由和动态路由
静态路由和动态路由是网络中路由器选择路径的两种主要方式,主要区别在于路由信息的维护方式及适用场景:
静态路由
- 定义
- 由管理员手动配置路由表,指定到达目标网络的固定路径。
- 特点
- 无自动更新:路径变化需人工修改。
- 无协议开销:不占用带宽和计算资源。
- 简单可控:适合小型网络或固定拓扑。
- 优缺点
- ✅ 安全性高,配置简单,资源消耗低。
- ❌ 扩展性差,拓扑变化时维护成本高。
- 应用场景
- 小型网络、默认路由、边缘网络出口。
动态路由
- 定义
- 路由器通过协议(如OSPF、BGP)自动交换路由信息,动态更新路由表。
- 特点
- 自动适应:根据网络变化(如链路故障)实时调整路径。
- 协议分类:
- 距离矢量(如RIP):基于跳数,定期广播路由表。
- 链路状态(如OSPF):同步全网拓扑,计算最短路径。
- 路径矢量(如BGP):用于跨自治系统(Internet)。
- 优缺点
- ✅ 扩展性强,自适应故障,减少人工干预。
- ❌ 协议开销大,配置复杂,可能引发路由环路。
- 应用场景
- 中大型网络、复杂拓扑、需冗余路径的环境。
4.2 简述网关的作用是什么,同一网段的主机如何通信
1.网关的作用
1、网关(Gateway)是连接不同网络的关键设备,类似于现实世界中的"海关"或"桥梁",主要功能包括:
- 网络互连:不同的网络(如局域网、城域网、广域网)通过网关连接,形成更大的互联网。
- 协议转换:如果两个网络使用不同的通信协议(如IPv4和IPv6、以太网和Wi-Fi),网关负责数据格式的转换。
- 路由选择:决定数据包应该传送到哪个网络(如从家庭局域网到互联网)。
- NAT(网络地址转换):将内部私有IP(如192.168.1.100)转换成公网IP,使多台设备共享一个公网IP上网。
- 安全防护:部分网关具备防火墙功能,过滤恶意流量,保护内部网络。
通俗理解:
- 网关就像邮局的中转站,负责把本地的信件(数据包)送到外部网络(如互联网),同时把外部的信件正确送到本地。
- 如果没有网关,局域网内的设备就无法访问外部网络(如百度、谷歌)
- 同一网段内的通信(不经过网关)
当两台主机在同一个网段(如192.168.1.10和192.168.1.20,子网掩码255.255.255.0),通信过程如下:
(1)ARP请求(获取目标MAC地址)
- 问题:主机A(192.168.1.10)想发送数据给主机B(192.168.1.20),但不知道主机B的MAC地址。
- 解决:主机A发送ARP广播请求(类似"谁是192.168.1.20?请告诉我你的MAC地址!")。
- 广播方式:交换机会洪泛(Flooding)该ARP请求,即向所有端口(除了来源端口)发送,确保全网段主机都能收到。
(2)ARP响应(目标主机回复MAC)
- 只有主机B(192.168.1.20)发现请求的IP是自己的,于是单播回复:"我是192.168.1.20,我的MAC是xx:xx:xx:xx:xx。"
- 主机A收到后,把IP→MAC的映射存入ARP缓存表,后续通信直接查表,无需再发ARP请求。
(3)数据封装与传输(二层交换)
- 主机A把数据封装成以太网帧(包含源/目标MAC、IP等信息),通过交换机发送。
- 交换机根据MAC地址表,精准转发到主机B(不经过路由器)。
关键点总结
- 不经过网关:因为目标IP在同一网段,数据直接在二层(MAC地址)完成交换。
- ARP的作用:把IP地址解析成MAC地址,确保数据能正确送达。
- 交换机的角色:根据MAC地址表转发数据,提高效率(相比集线器的广播方式)。
3、跨网段通信(需经过网关)
如果主机A(192.168.1.10)想访问百度(220.181.38.148):
- 发现目标IP不在本地网段,数据包发送给默认网关(如路由器192.168.1.1)。
- 网关负责把数据包路由到互联网,最终到达百度服务器。
结论:
- 同网段通信:直接通过MAC地址(二层交换),不经过网关。
- 跨网段通信:必须经过网关(路由器)进行路由转发。
4.3 简述CSRF攻击的思想以及解决方法
- CSRF攻击原理(跨站请求伪造)
CSRF(Cross-Site Request Forgery) 是一种利用用户已登录的会话(如Cookie),在用户不知情的情况下,以用户身份执行恶意操作的攻击方式。
攻击流程(图解)
用户浏览器 恶意网站(B) 受信任网站(A)
│ │ │
├── 1. 登录A ───────▶│ │
│ (生成Cookie) │ │
│ │ │
├── 2. 访问B ───────▶│ │
│ │ │
│ 3. B返回恶意代码───▶│ │
│ (如自动转账请求) │ │
│ │ │
├── 4. 浏览器自动─────▶───────────────────▶
│ 携带Cookie访问A │ │
│ │ │
│ 5. A认为请求合法───▶───────────────────▶
│ 执行恶意操作 │ │
关键点:
- 受害者必须已登录A网站(Cookie有效)。
- 恶意网站B诱导用户访问(如钓鱼邮件、恶意广告)。
- 浏览器自动携带Cookie,A网站无法区分请求是用户还是攻击者发起的。
- CSRF防御方法
(1)Referer验证(不推荐)
原理:检查HTTP请求头中的Referer字段,确保请求来自合法域名。
正常请求:
Referer: https://bank.com/transfer
CSRF攻击请求:
Referer: https://evil.com/malicious-page
问题:
- 隐私限制:部分浏览器或用户设置会屏蔽Referer。
- 误判:从搜索引擎跳转的请求可能被误拦截。
2)Token验证(推荐)
原理:服务器生成随机Token,客户端提交时必须携带该Token。
流程:
- 用户访问A网站 ────▶ 服务器生成Token(如csrftoken=abc123)并存入Session。
- 服务器返回页面 ────▶ Token嵌入表单(隐藏字段)或HTTP头(如X-CSRF-Token)。
- 用户提交请求 ────▶ 浏览器自动携带Token。
- 服务器验证Token ──▶ 匹配则执行,否则拒绝。
图解Token防御:
用户浏览器 恶意网站(B) 受信任网站(A)
│ │ │
├── 1. 登录A ───────▶│ │
│ (获取Token) │ │
│ │ │
├── 2. 访问B ───────▶│ │
│ │ │
│ 3. B返回恶意代码───▶│ │
│ (无Token或错误Token)│ │
│ │ │
├── 4. 请求发送到A ──▶───────────────────▶
│ (Token无效) │ │
│ │ │
│ 5. A拒绝请求 ──────▶───────────────────▶
为什么Token有效?
- Token无法被恶意网站获取:因为同源策略(Same-Origin Policy),B网站无法读取A网站的Token。
- 每次会话唯一:攻击者无法预测或伪造Token。
(3)SameSite Cookie(浏览器级防护)
原理:通过设置Cookie的SameSite属性,限制跨站请求携带Cookie。
- SameSite=Strict:完全禁止跨站携带Cookie(可能导致用户体验问题)。
- SameSite=Lax(推荐):允许安全跨站请求(如导航链接),但阻止POST等敏感请求。
(4)二次验证(增强安全性)
适用场景:敏感操作(如转账、修改密码)。
- 方式:要求用户重新输入密码、短信验证码或邮箱确认。
总结
- 必选方案:CSRF Token + SameSite Cookie(兼顾安全性与兼容性)。
- 关键操作:增加二次验证(如短信验证码)。
- 避免依赖Referer:因其不可靠,仅作为辅助手段。
核心思想:
让攻击者无法伪造合法请求!
- Token确保请求来源可信。
- SameSite Cookie阻止跨站滥用会话
4.4说说 MAC地址和IP地址分别有什么作用
- MAC地址的作用
- 设备唯一标识:每个网卡出厂时都有一个全球唯一的MAC地址(如 00:1A:2B:3C:4D:5E)。
- 局域网通信:在同一个网络(如家庭Wi-Fi)中,设备通过MAC地址直接通信。
- 示例:电脑A(MAC: AA:BB:CC:DD:EE:FF)向电脑B(MAC: 11:22:33:44:55:66)发送文件时,交换机会根据MAC地址转发数据。
- ARP协议:通过ARP(地址解析协议)将IP地址转换为MAC地址(如 192.168.1.100 → AA:BB:CC:DD:EE:FF)。
- IP地址的作用
- 逻辑寻址:IP地址用于跨网络通信(如从家庭网络访问百度服务器)。
- 示例:你的手机(IP: 192.168.1.100)访问百度(IP: 220.181.38.148),数据包经过路由器(网关)转发到互联网。
- 路由选择:路由器根据IP地址决定数据包的下一跳路径(如从中国到美国的服务器)。
- NAT(网络地址转换):将私有IP(如 192.168.1.100)转换为公网IP(如 120.240.10.20),实现多设备共享上网。
关键区别
- MAC地址:像你的身份证号(唯一且不变),用于本地身份识别。
- IP地址:像你的邮寄地址(可变化),用于全球范围内的通信寻址。
通信流程举例(访问网站)
- 本地网络:你的电脑(IP: 192.168.1.100)通过MAC地址找到路由器(网关)。
- 跨网络:路由器将你的私有IP转换为公网IP,通过IP地址找到目标服务器(如百度)。
- 返回数据:百度服务器将数据送回你的公网IP,路由器再根据MAC地址转发到你的电脑。
常见问题
Q:为什么既需要MAC地址又需要IP地址?
- MAC地址解决同一网络内设备间的直接通信(如交换机转发)。
- IP地址解决跨网络的路由问题(如从你家到谷歌服务器)。
Q:MAC地址会被泄露吗?
- 会,但仅在局域网内(如公共Wi-Fi),攻击者可利用MAC地址进行ARP欺骗。
Q:IP地址和MAC地址能伪造吗?
- MAC地址:可手动修改(如 ifconfig eth0 hw ether 00:11:22:33:44:55)。
- IP地址:可伪造发送源IP(如DDoS攻击),但响应数据无法正常接收。
4.5简述 TCP 三次握手和四次挥手的过程
三次握手
1)第一次握手:建立连接时,客户端向服务器发送SYN包(seq=x),请求建立连接,等待确认
2)第二次握手:服务端收到客户端的SYN包,回一个ACK包(ACK=x+1)确认收到,同时发送一个SYN
包(seq=y)给客户端
3)第三次握手:客户端收到SYN+ACK包,再回一个ACK包(ACK=y+1)告诉服务端已经收到
4)三次握手完成,成功建立连接,开始传输数据
四次挥手
1)客户端发送FIN包(FIN=1)给服务端,告诉它自己的数据已经发送完毕,请求终止连接,此时客户
端不发送数据,但还能接收数据
2)服务端收到FIN包,回一个ACK包给客户端告诉它已经收到包了,此时还没有断开socket连接,而是
等待剩下的数据传输完毕
3)服务端等待数据传输完毕后,向客户端发送FIN包,表明可以断开连接
4)客户端收到后,回一个ACK包表明确认收到,等待一段时间,确保服务端不再有数据发过来,然后彻
底断开连接
4.6 说说 TCP 2次握手行不行?为什么要3次
TCP(传输控制协议)采用三次握手(3-Way Handshake)建立连接,目的是确保双方都能正常收发数据,并防止重复SYN导致建立混乱的连接。
如果只用2次握手,会导致以下严重问题:
- 2次握手的问题(为什么不行?)
假设客户端(Client)和服务器(Server)尝试建立TCP连接:
场景1:网络延迟导致重复SYN
- Client发送SYN=1(seq=x),但由于网络延迟,这个包很久才到Server。
- Client超时重传SYN=1(seq=y),这次正常到达,Server返回SYN+ACK(seq=z, ack=y+1)。
- 2次握手完成,双方进入ESTABLISHED状态。
- 延迟的SYN(seq=x)终于到达Server,Server误认为这是新请求,直接返回SYN+ACK(seq=w, ack=x+1)。
- Client收到后一脸懵逼:
- 它没有发送seq=x的SYN(已经改用seq=y了),所以会回复RST(重置连接)。
- 但Server已经认为连接建立,可能开始发送数据,导致资源浪费。
问题:2次握手无法区分延迟的旧SYN包和正常的新SYN包,可能建立无效连接。
场景2:Server无法确认Client的接收能力
在2次握手中:
- Client → Server:SYN(seq=x)
- Server → Client:SYN+ACK(seq=y, ack=x+1)
- 握手结束
但此时:
- Server不知道Client是否能收到自己的SYN+ACK(可能Client已经崩溃或网络不通)。
- 如果Server直接进入ESTABLISHED状态并发送数据,但Client根本没收到SYN+ACK,导致数据丢失。
问题:2次握手无法确保双方收发能力正常,可能单方面认为连接已建立。
- 3次握手如何解决这些问题?
三次握手流程:
- Client → Server:SYN(seq=x)
- Client进入SYN_SENT状态,表示"我想建立连接"。
- Server → Client:SYN+ACK(seq=y, ack=x+1)
- Server进入SYN_RCVD状态,表示"我收到你的SYN了,我也同意建立连接"。
- Client → Server:ACK(ack=y+1)
- Client进入ESTABLISHED状态,表示"我收到你的SYN+ACK了,连接已建立"。
- Server收到ACK后也进入ESTABLISHED状态。
关键点:
- 第三次握手(ACK)让Server确认Client是活跃的,能正常通信。
- 序列号(seq)和确认号(ack)机制避免了历史SYN包的混淆。
- 为什么不是4次握手?
- 3次已经足够保证双方收发能力,再多一次(如Server再回复一个ACK)只是冗余,不会提高可靠性。
- TCP设计追求最小必要交互次数,3次是理论和实践上的最优解。
4.7 在建立连接时,序列号(seq)和确认号(ack)的关系
在TCP三次握手过程中,序列号(Sequence Number, seq)和确认号(Acknowledgment Number, ack)的作用至关重要,它们共同确保数据的有序传输和可靠性。
- 序列号(seq)的作用
- 标识数据字节流的顺序:每个TCP报文段都会携带一个seq,表示该报文段第一个字节的编号。
- 初始序列号(ISN, Initial Sequence Number):在握手阶段,双方会随机生成一个初始seq(防止历史报文干扰)。
- 后续数据包的seq:按数据长度递增(如发送100字节后,下一个seq = 当前seq + 100)。
示例:
- 客户端发送SYN,seq = 1000(随机生成)。
- 服务器发送SYN+ACK,seq = 2000(随机生成)。
- 确认号(ack)的作用
- 确认已收到的数据:ack表示"期望收到的下一个字节的编号",即ack = 对方最后收到的seq + 数据长度 + 1(SYN/FIN占1个序号)。
- 保证数据不丢失:收到ack后,发送方知道对方已成功接收数据。
示例:
- 客户端发送SYN, seq=1000,服务器回复SYN+ACK, ack=1001(表示"我收到了你的seq=1000,期待你的seq=1001")。
- 客户端回复ACK, ack=2001(表示"我收到了你的seq=2000,期待你的seq=2001")。
-
三次握手中的seq和ack交互
Client (seq=x) Server (seq=y)
│ │
│ 1. SYN, seq=x │
│──────────────────────────────────────>│
│ │
│ 2. SYN+ACK, seq=y, ack=x+1 │
│<──────────────────────────────────────│
│ │
│ 3. ACK, seq=x+1, ack=y+1 │
│──────────────────────────────────────>│
│ │
│ 连接建立! │
详细解析:
-
第一次握手(Client → Server)
- Client发送SYN,seq=x(随机初始值)。
- 含义:"我想建立连接,我的数据从x开始编号。"
-
第二次握手(Server → Client)
- Server发送SYN+ACK,seq=y(随机初始值),ack=x+1。
- 含义:
- seq=y:"我的数据从y开始编号。"
- ack=x+1:"我收到了你的SYN(seq=x),期待你的下一个数据是x+1。"
-
第三次握手(Client → Server)
- Client发送ACK,seq=x+1(因为SYN占1个序号),ack=y+1。
- 含义:
- ack=y+1:"我收到了你的SYN(seq=y),期待你的下一个数据是y+1。"
- seq=x+1:由于SYN已占用x,下一个数据从x+1开始。
-
为什么ack是seq+1?
- SYN和FIN各占1个序号(尽管不携带数据)。
- 当Client发送SYN, seq=x,Server的ack=x+1表示:"SYN(x)已收到,期待x+1。"
- 同理,FIN(关闭连接)也会让ack增加1。
示例:
- 如果Client发送SYN, seq=1000,Server回复ack=1001。
- 如果Client发送FIN, seq=5000,Server回复ack=5001。
- 关键总结
字段 作用 示例(三次握手)
seq 标识发送数据的起始编号 Client: SYN, seq=1000
ack 确认已收到的数据,期望下一个字节 Server: SYN+ACK, ack=1001
seq+1规则 SYN/FIN占1个序号 SYN使ack=seq+1
核心结论:
- seq 用于标识自己发送的数据流。
- ack 用于确认对方的数据,并告知期望的下一个字节。
- 三次握手的seq和ack确保双方能正确同步数据编号,防止历史报文干扰。
- 常见问题
Q1:为什么初始seq是随机的?
- 防止黑客伪造历史报文(如预测seq发起攻击)。
Q2:如果ack丢失会怎样?
- 发送方会超时重传(TCP的可靠性机制)。
Q3:数据传输时seq和ack如何变化?
- 比如Client发送100字节(seq=1000),Server回复ack=1101(1000 + 100 + 1)。
最终总结
TCP通过三次握手 + seq/ack机制,确保:
- 双方能正常收发数据(验证通信能力)。
- 数据编号正确同步(防止乱序或重复)。
- 连接可靠建立(避免历史报文干扰)。
"三次握手"是TCP可靠性的基石,而seq和ack是其核心实现方式!
4.8 简述 TCP 慢启动
慢启动(Slow Start)是 TCP 拥塞控制的核心机制之一,用于在连接初期快速探测可用带宽,同时避免因发送速率过高而导致网络拥塞。它的核心特点是指数级增长拥塞窗口(cwnd),直到遇到丢包或达到慢启动阈值(ssthresh)后,转为线性增长(拥塞避免阶段)。
- 慢启动的基本原理
(1) 初始阶段
- 初始拥塞窗口(Initial cwnd):TCP 连接刚建立时,发送方的拥塞窗口 cwnd 通常设置为 1 MSS(Maximum Segment Size,最大报文段大小)。现代 TCP(如 Linux)可能设置为 10 MSS(RFC 6928)。
- 慢启动阈值(ssthresh):初始值通常较高(如 65535 字节),但一旦发生丢包,会动态调整。
(2) 指数增长阶段
- 每收到一个 ACK,cwnd 增加 1 MSS:
- 例如:
- 第 1 个 RTT:发送 1 个报文 → 收到 1 个 ACK → cwnd = 2。
- 第 2 个 RTT:发送 2 个报文 → 收到 2 个 ACK → cwnd = 4。
- 第 3 个 RTT:发送 4 个报文 → 收到 4 个 ACK → cwnd = 8。
- 增长模式:cwnd 呈 指数增长(1 → 2 → 4 → 8 → 16...)。
- 例如:
(3) 退出慢启动的条件
- ① 达到慢启动阈值(ssthresh):
- 当 cwnd ≥ ssthresh 时,TCP 进入 拥塞避免(Congestion Avoidance) 阶段,改为 线性增长(每 RTT 增加 1 MSS)。
- ② 检测到丢包:
- 如果发生 超时(Timeout) 或 收到 3 个重复 ACK(DupACK),TCP 认为网络拥塞,会:
- 降低 ssthresh:设为当前 cwnd 的一半(ssthresh = cwnd / 2)。
- 重置 cwnd:
- 传统 TCP(Tahoe):cwnd = 1,重新慢启动。
- 改进 TCP(Reno):进入 快速恢复(Fast Recovery),cwnd 降为 ssthresh 后继续传输。
- 如果发生 超时(Timeout) 或 收到 3 个重复 ACK(DupACK),TCP 认为网络拥塞,会:
- 慢启动的示例
示例 1:正常慢启动(无丢包)
-
初始参数:
- cwnd = 1 MSS,ssthresh = 8 MSS。
- 过程:
RTT 轮次 cwnd 变化 发送数据量 总量(累计)
1 1 → 2 1 1
2 2 → 4 2 3 (1+2)
3 4 → 8 4 7 (1+2+4)
4 8 → 9 8 15 (1+2+4+8)- RTT 4 时 cwnd = 8(达到 ssthresh),进入 拥塞避免(线性增长)。
示例 2:发生丢包(触发拥塞控制)
- RTT 4 时 cwnd = 8(达到 ssthresh),进入 拥塞避免(线性增长)。
- 假设在 RTT 3 时发生丢包:
- 调整参数:
- ssthresh = cwnd / 2 = 4(新阈值)。
- cwnd = 1(重新慢启动)。
- 重新慢启动:
- cwnd 再次从 1 开始增长,直到 cwnd = 4(新 ssthresh),然后进入线性增长。
- 调整参数:
- 慢启动的优化
- 初始窗口扩大(RFC 6928):
- 现代 TCP 允许 cwnd 初始值设为 10 MSS,加快传输速度。
- 混合慢启动(Hybrid Slow Start):
- 结合 延迟测量,提前检测拥塞,避免过度增长。
- 快速恢复(Fast Recovery):
- 在部分丢包(DupACK)时,不重置 cwnd = 1,而是降为 ssthresh 并继续传输。
4.慢启动的意义
- 在部分丢包(DupACK)时,不重置 cwnd = 1,而是降为 ssthresh 并继续传输。
- 快速探测带宽:初期指数增长可以高效利用空闲网络资源。
- 避免拥塞崩溃:通过丢包反馈动态调整发送速率,防止网络过载。
- 适应动态网络:能根据网络状况自动调整传输速率。
慢启动是 TCP 拥塞控制的关键机制,它平衡了传输效率和网络稳定性,确保数据流能快速适应网络变化。
4.9说说 TCP 如何保证有序
主机每次发送数据时,TCP就给每个数据包分配一个序列号并且在一个特定的时间内等待接收主机,对分配的这个序列号进行确认,如果发送主机在一个特定时间内没有收到接收主机的确认,则发送主机会重传此数据包。
接收主机利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,接收主机一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。
具体步骤如下:
(1)为了保证数据包的可靠传递,发送方必须把已发送的数据包保留在缓冲区;
(2)并为每个已发送的数据包启动一个超时定时器;
(3)如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区;
(4)否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。
(5)接收方收到数据包后,先进行CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,如果接收方正好也有数据要发给发送方,应答包也可方在数据包中捎带过去。
4.10 说说 TCP 常见的拥塞控制算法有哪些
TCP 常见的拥塞控制算法主要包括以下几种,它们在不同的网络环境下通过动态调整发送速率来避免网络拥塞:
- Tahoe
- 核心机制:基于慢启动(Slow Start)、拥塞避免(Congestion Avoidance)和快速重传(Fast Retransmit)。
- 特点:
- 当检测到丢包(超时或重复ACK)时,将拥塞窗口(cwnd)重置为 1,重新进入慢启动。
- 保守策略,效率较低,尤其在轻微拥塞时表现不佳。
- Reno
- 改进点:在 Tahoe 基础上增加了快速恢复(Fast Recovery)。
- 特点:
- 对重复ACK触发的丢包(非超时)采用快速恢复:cwnd减半后线性增长,而非直接重置。
- 区分超时丢包和快速重传丢包,减少激进回退。
- NewReno
- 改进点:优化 Reno 的快速恢复阶段,解决多个数据包丢失时的性能问题。
- 特点:
- 在快速恢复期间,仅当所有丢失包被确认后才退出该阶段。
- 减少重复超时的可能性,提高吞吐量。
- BIC (Binary Increase Congestion Control)
- 核心思想:通过二分搜索动态调整 cwnd,寻找最优窗口大小。
- 适用场景:高带宽延迟积(BDP)网络(如长肥管道)。
- 特点:
- 窗口增长阶段分为加性增和二分搜索增,平衡效率和公平性。
- CUBIC
- 现代默认算法:Linux 内核的默认拥塞控制算法(2005年后)。
- 核心改进:
- 用三次函数(立方函数)替代线性增长,窗口增长与时间相关(而非ACK事件)。
- 更公平地竞争带宽,在高BDP网络中表现优异。
- 独立于RTT(往返时间),适合广域网。
- BBR (Bottleneck Bandwidth and Round-trip propagation time)
- 革命性设计:由 Google 提出(2016),基于测量而非丢包或延迟。
- 核心原理:
- 动态估计网络瓶颈带宽(BtlBW)和最小RTT,计算最优发送速率。
- 避免传统算法因丢包导致的性能下降,尤其适合高速网络。
- 特点:高吞吐、低延迟,但公平性与传统算法共存仍需优化。
其他变种
- Vegas:基于RTT变化预测拥塞,提前调整速率(但实际部署较少)。
- Compound TCP(微软):结合延迟和丢包信号,用于 Windows 系统。
- Hybla:针对高延迟网络(如卫星通信)优化。
对比总结
算法 触发信号 核心策略 适用场景
Tahoe 丢包/超时 重置窗口,慢启动 早期网络
Reno 重复ACK 快速恢复 + 减半 普通网络
CUBIC 丢包 三次函数增长 高BDP、现代互联网
BBR 带宽/RTT测量 模型驱动速率控制 高速、高丢包网络
选择建议
- 传统网络:CUBIC(平衡性佳,广泛兼容)。
- 高速网络:BBR(避免Bufferbloat,提升吞吐)。
- 嵌入式系统:Reno/NewReno(实现简单)。
4.11 简述 TCP 超时重传
TCP可靠性中最重要的一个机制是处理数据超时和重传。TCP协议要求在发送端每发送一个报文段,就启动一个定时器并等待确认信息;接收端成功接收新数据后返回确认信息。若在定时器超时前数据未能被确认,TCP就认为报文段中的数据已丢失或损坏,需要对报文段中的数据重新组织和重传。
4.12 说说 TCP 可靠性保证
TCP主要提供了检验和、序列号/确认应答、超时重传、最大消息长度、滑动窗口控制等方法实现了可靠性传输。
1、检验和
TCP 校验和(Checksum)是一种 差错检测机制,用于确保 TCP 段(Segment)在传输过程中没有被篡改或损坏。如果校验和验证失败,接收端会 丢弃该 TCP 段,并要求发送端 重传。
TCP 校验和计算 3 部分数据:TCP 伪首部(12 字节)、TCP 首部(Header)
TCP 数据(Payload)。伪首部包含 IP 层的部分信息(如源/目标 IP 地址),确保 TCP 数据不会被错误地路由到其他主机。伪首部是 临时构造的数据,仅用于校验和计算,不会真正传输。
接收端:提取伪首部信息(从 IP 层获取源/目标 IP 地址)、重新计算校验和(伪首部 + TCP 首部 + 数据)。比对校验和?
- 如果校验和 == 0:数据正确 ✅。
- 如果校验和 ≠ 0:数据损坏 ❌,丢弃并触发重传
2、序列号/确认应答
- 序列号(Seq):
- 每个字节的数据都会被分配一个唯一序列号,标识数据的顺序。
- 例如,发送方发送 Seq=1, len=100,则下一段数据从 Seq=101 开始。
- 确认应答(ACK):
- 接收方收到数据后,返回 ACK=下一个期望的序列号(如收到 Seq=1, len=100,则回复 ACK=101)。
- 累积确认:若 ACK=101 表示序列号 1~100 的数据已全部接收。
- 作用:确保数据按序到达,并通知发送方哪些数据已被成功接收。
-
超时重传
超时重传是指发送出去的数据包到接收到确认包之间的时间,如果超过了这个时间会被认为是丢包了,需要重传。
我们知道,一来一回的时间总是差不多的,都会有一个类似于平均值的概念。比如发送一个包到接收端收到这个包一共是0.5s,然后接收端回发一个确认包给发送端也要0.5s,这样的两个时间就是RTT(往返时间)。然后可能由于网络原因的问题,时间会有偏差,称为抖动(方差)。超时重传的时间大概是比往返时间+抖动值还要稍大的时间。
在重发的过程中,假如一个包经过多次的重发也没有收到对端的确认包,那么就会认为接收端
异常,强制关闭连接。并且通知应用通信异常强行终止。
- 最大消息长度(MSS, Maximum Segment Size)
- 作用:限制单个 TCP 报文段的最大数据长度(不包括头部)。
- 协商机制:
- 在三次握手时通过 MSS 选项告知对方(通常基于 MTU 计算,如以太网中 MSS=1460)。
- 意义:
- 避免 IP 层分片(分片会降低效率,增加丢包风险)。
5.滑动窗口
上面提到的超时重传的机制存在效率低下的问题,发送一个包到发送下一个包要经过一段时间才可以。所以我们就想着能不能不用等待确认包就发送下一个数据包呢?这就提出了一个滑动窗口的概念。
窗口的大小就是在无需等待确认包的情况下,发送端还能发送的最大数据量。这个机制的实现就是使用了大量的缓冲区,通过对多个段进行确认应答的功能。通过下一次的确认包可以判断接收端是否已经接收到了数据,如果已经接收了就从缓冲区里面删除数据。
在窗口之外的数据就是还未发送的和对端已经收到的数据。那么发送端是怎么样判断接收端有没有接收到数据呢?或者怎么知道需要重发的数据有哪些呢?通过下面这个图就知道了。
如上图,接收端在没有收到自己所期望的序列号数据之前,会对之前的数据进行重复确认。发送端
在收到某个应答包之后,又连续3次收到同样的应答包,则数据已经丢失了,需要重发。
4.13 简述 TCP 滑动窗口以及重传机制
1、滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
TCP的滑动窗口解决了端到端的流量控制问题,允许接受方对传输进行限制,直到它拥有足够的缓冲空间来容纳更多的数据。
2、TCP在发送数据时会设置一个计时器,若到计时器超时仍未收到数据确认信息,则会引发相应的超时或基于计时器的重传操作,计时器超时称为重传超时(RTO) 。另一种方式的重传称为快速重传,通常发生在没有延时的情况下。若TCP累积确认无法返回新的ACK,或者当ACK包含的选择确认信息(SACK)表明出现失序报文时,快速重传会推断出现丢包,需要重传。
4.14说说滑动窗口过小怎么办
我们可以假设窗口的大小是1,也是就每次只能发送一个数据,并且发送方只有接受方对这个数据进行确认了以后才能发送下一个数据。如果说窗口过小,那么当传输比较大的数据的时候需要不停的对数据进行确认,这个时候就会造成很大的延迟。
4.15TCP 三次握手及握手消息丢失的详细分析
TCP 使用三次握手建立可靠连接,过程中任何一个消息丢失都会影响连接状态。以下是针对三次握手中各消息丢失情况的详细说明:
- 第一次握手消息(SYN)丢失
- 现象:Client 发送 SYN 报文后未收到 SYN-ACK 响应。
- 处理机制:
- Client 触发超时重传,根据系统配置(如 Linux 的 tcp_syn_retries,默认 6 次)重发 SYN。
- 每次重传间隔指数增长(如 1s, 2s, 4s...)。
- 若重试耗尽仍无响应,Client 返回 ETIMEDOUT 错误。
- 关键点:Server 因未收到 SYN,完全不知连接请求,不会分配资源。
- 第二次握手消息(SYN-ACK)丢失
- 现象:Server 发送 SYN-ACK 后未收到 Client 的 ACK。
- 处理机制:
- Server 通过 tcp_synack_retries(默认 5 次)重传 SYN-ACK,间隔为 3s、6s、12s 等。
- 若最终未收到 ACK,Server 关闭半连接(状态从 SYN_RCVD 回到 CLOSED)。
- Client 视角:
- Client 的 connect() 已发出 SYN,但未收到 SYN-ACK,会像第一次握手丢失一样重传 SYN。
- 若 Server 的 SYN-ACK 在 Client 重传 SYN 前到达,Client 会正常响应 ACK(此时可能因延迟导致乱序,但 TCP 会处理)。
- 第三次握手消息(ACK)丢失
- 现象:Client 发送 ACK 后,Server 未收到 ACK。
- Server 处理:
- Server 处于 SYN_RCVD 状态,会重传 SYN-ACK(如 3s、6s、12s...),直到达到 tcp_synack_retries 限制后关闭连接。
- Client 处理:
- Client 认为连接已建立(状态为 ESTABLISHED),因 connect() 在收到 SYN-ACK 后即成功。
- 若 Client 发送数据:
- 正常情况:Server 收到数据后,即使之前未收到 ACK,也会将状态转为 ESTABLISHED(数据包隐含 ACK)。
- Server 已关闭连接:Server 回复 RST 重置连接,Client 收到后触发错误(如 ECONNRESET)。
- 关键点:
- Linux 优化:Server 在收到数据包时会检查序列号,若合法则直接建立连接(无需依赖显式 ACK)。
- 若 Client 不发送数据,Server 最终因超时关闭连接,但 Client 仍认为连接有效(直到尝试通信时发现错误)。
4.16TIME_WAIT 状态(2MSL 等待)的简要说明
- 为什么需要 TIME_WAIT?
- 问题背景:TCP 四次挥手关闭连接时,主动关闭方(如 Client)在发送最后一个 ACK 后,不能立即关闭连接,因为:
- 网络不可靠:最后一个 ACK 可能丢失,导致被动关闭方(如 Server)收不到确认,会重传 FIN。
- 防止旧连接的数据干扰新连接:如果立即复用相同的 IP + 端口,可能会收到之前延迟的旧数据包,导致混淆。
- TIME_WAIT 的作用
- 等待 2MSL(2 × Maximum Segment Lifetime):
- MSL:报文段在网络中的最大存活时间(通常 30s-2min,Linux 默认 60s)。
- 2MSL 等待:
- 确保最后一个 ACK 到达对端:如果 ACK 丢失,被动关闭方会重传 FIN,主动关闭方可以再次发送 ACK。
- 让网络中残留的旧数据包失效:等待 2MSL 后,所有属于该连接的延迟报文都会消失,避免影响新连接。
- TIME_WAIT 的影响
- 连接资源暂时不可用:
- 在 2MSL 期间,该连接的四元组(源 IP、源端口、目标 IP、目标端口)不能被复用。
- 如果频繁短连接(如 HTTP 请求),可能导致端口耗尽(TIME_WAIT 过多)。
- 解决方案:
- 调整 net.ipv4.tcp_tw_reuse(允许复用 TIME_WAIT 连接)。
- 让 Server 主动关闭连接(减少 Client 的 TIME_WAIT)。
- 为什么不是直接进入 CLOSED?
- 如果最后一个 ACK 丢失,被动关闭方(Server)会一直重传 FIN,而主动关闭方(Client)已经关闭连接,无法响应,导致 Server 长时间卡在 LAST_ACK 状态。
- TIME_WAIT 确保可靠关闭,即使最后一个 ACK 丢失,也能让双方最终正确关闭。
总结
关键点 说明
TIME_WAIT 的时长 2 × MSL(Linux 默认 60s,故 TIME_WAIT 通常 120s)
作用 (1) 确保最后一个 ACK 到达;(2) 让旧数据包失效
影响 占用连接资源,可能导致端口耗尽
优化方法 tcp_tw_reuse、让 Server 主动关闭
简单来说:
TIME_WAIT 是 TCP 对网络不可靠的一种保护机制,确保连接能彻底关闭,避免脏数据干扰新连接。
4.17 简述什么是 MSL,为什么客户端连接要等待2MSL的时间才能完全关闭
1、MSL是Maximum Segment Lifetime的英文缩写,可译为"最长报文段寿命",它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
2、为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
3、两个理由:
1)保证客户端发送的最后一个ACK报文段能够到达服务端。
这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。
2)防止"已失效的连接请求报文段"出现在本连接中。
客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
4.18 说说什么是 TCP 粘包和拆包?
TCP是个"流"协议,所谓流,就是没有界限的一串数据。(大家可以想想河里的流水,是连成一片的,其间并没有分界线。)TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。
假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4种情况:
(1)服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包;
(2)服务端一次接收到了两个数据包,D1和D2粘合在一起,被称为TCP粘包;
(3)服务端分两次读取到了两个数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这被称为TCP拆包;
(4)服务端分两次读取到了两个数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余内容D1_2和D2包的整包。
如果此时服务端TCP接收滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种可能,即服务端分多次才能将D1和D2包接收完全,期间发生多次拆包。
4.19说说 TCP 与 UDP 在网络协议中的哪一层,他们之间有什么区别?
TCP和UDP协议都是传输层协议。二者的区别主要有:
-
基于连接vs无连接
TCP是面向连接的协议。
UDP是无连接的协议。UDP更加适合消息的多播发布,从单个点向多个点传输消息。
-
可靠性
TCP提供交付保证,传输过程中丢失,将会重发。
UDP是不可靠的,不提供任何交付保证。(网游和视频的丢包情况)
-
有序性
TCP保证了消息的有序性,即使到达客户端顺序不同,TCP也会排序。
UDP不提供有序性保证。
-
数据边界
TCP不保存数据边界。虽然TCP也将在收集所有字节之后生成一个完整的消息,但是这些信息在传给传输给接受端之前将储存在TCP缓冲区,以确保更好的使用网络带宽。
UDP保证数据边界。
在UDP中,数据包单独发送的,只有当他们到达时,才会再次集成。包有明确的界限来说明哪些包已经收到,这意味着在消息发送后,在接收器接口将会有一个读操作,来生成一个完整的消息。
-
速度
TCP速度慢
UDP速度快。应用在在线视频媒体,电视广播和多人在线游戏。
-
发送消耗
TCP是重量级。
UDP是轻量级。
因为UDP传输的信息中不承担任何间接创造连接,保证交货或秩序的的信息。这也反映在于报头大小。
-
报头大小
TCP头大。
一个TCP数据包报头的大小是20字节。
TCP报头中包含序列号,ACK号,数据偏移量,保留,控制位,窗口,紧急指针,可选项,填充项,校验位,源端口和目的端口。
UDP头小。
UDP数据报报头是8个字节。而UDP报头只包含长度,源端口号,目的端口,和校验和。
-
拥塞或流控制
TCP有流量控制。
在任何用户数据可以被发送之前,TCP需要三数据包来设置一个套接字连接。TCP处理可靠性和拥塞控制。
UDP不能进行流量控制。
-
应用
由于TCP提供可靠交付和有序性的保证,它是最适合需要高可靠并且对传输时间要求不高的应用。
UDP是更适合的应用程序需要快速,高效的传输的应用,如游戏。
UDP是无状态的性质,在服务器端需要对大量客户端产生的少量请求进行应答的应用中是非常有用的。
在实践中,TCP被用于金融领域,如FIX协议是一种基于TCP的协议,而UDP是大量使用在游戏和娱乐场所。
4.20说说从系统层面上,UDP 如何保证尽量可靠?
1、UDP仅提供了最基本的数据传输功能,至于传输时连接的建立和断开、传输可靠性的保证这些UDP统统不关心,而是把这些问题抛给了UDP上层的应用层程序去处理,自己仅提供传输层协议的最基本功能。
2、最简单的方式是在应用层模仿传输层TCP的可靠性传输。下面不考虑拥塞处理,可靠UDP的简单设计。
添加seq/ack机制,确保数据发送到对端
添加发送和接收缓冲区,主要是用户超时重传。
添加超时重传机制。
4.21TCP 延迟 ACK(Delayed ACK)与累计应答(Cumulative ACK)
- 延迟 ACK(Delayed ACK)
作用:减少 ACK 报文的数量,提高网络效率。
原理:
- 接收方收到数据后,不立即回复 ACK,而是等待一段时间(通常 200ms,取决于系统配置)。
- 如果在等待期间:
- 有数据要发送:则捎带 ACK(Piggybacking),合并发送(如 HTTP 响应 + ACK)。
- 无数据要发送:超时后单独发送 ACK。
优点:
- 减少小包(ACK 报文)的数量,降低网络负载。
- 提高带宽利用率(捎带 ACK 避免单独传输)。
缺点:
-
可能增加延迟(如等待 200ms 才确认)。
-
在某些实时性要求高的场景(如 SSH、游戏)可能需关闭(TCP_QUICKACK 选项)。
- 累计应答(Cumulative ACK)
作用:简化 ACK 机制,确保可靠传输。
原理:
- 接收方通过 一个 ACK 报文确认所有连续收到的数据。
- 例如:收到序列号 1-1000 和 1001-2000 的数据包后,回复 ACK 2001(表示期望下一个包从 2001 开始)。
- 如果中间有丢失(如 1001-2000 丢失),即使收到 2001-3000,仍回复 ACK 1001(要求重传丢失部分)。
优点:
- 减少 ACK 数量(无需为每个数据包单独确认)。
- 支持快速重传(发送方收到 3 个重复 ACK 即触发重传)。
缺点:
- 无法精确确认非连续数据(需依赖 选择性确认 SACK 扩展)。
对比总结
特性 延迟 ACK(Delayed ACK) 累计应答(Cumulative ACK)
目的 减少 ACK 报文数量 用一个 ACK 确认连续数据
触发条件 定时器超时或捎带数据 收到数据后立即确认(无延迟)
优化方向 降低网络小包流量 简化确认逻辑,支持快速重传
依赖机制 定时器管理 序列号(Sequence Number)
典型场景 HTTP 请求-响应交互 大数据传输(如文件下载)
总结
- 延迟 ACK:"等一等再回复",合并 ACK 提升效率。
- 累计应答:"一个 ACK 确认所有连续数据",简化重传逻辑。
- 两者协作:延迟期间积累数据,最终通过累计 ACK 高效确认。
4.22 服务器怎么判断客户端断开了连接
1、检测连接是否丢失的方法大致有两种:keepalive和heart-beat
2、TCP Keepalive 工作机制
工作流程(以Linux默认参数为例):
-
空闲检测:连接无数据交互持续tcp_keepalive_time(默认7200秒/2小时)
-
开始探测:
- 发送空ACK包,等待响应
- 无响应则每隔tcp_keepalive_intvl(默认75秒)重试
- 最多尝试tcp_keepalive_probes次(默认9次)
-
判定死亡:全部尝试失败后关闭连接
-
应用层Heartbeat实现
- 周期性发送心跳包(如每 30秒 发送 PING)
- 等待客户端回复 PONG,超时未回复判定断开
(应用层实现)一个简单的heart-beat实现一般测试连接是否中断采用的时间间隔都比较短,可以很快的决定连接是否中断。并且,由于是在应用层实现,因为可以自行决定当判断连接中断后应该采取的行为,而keepalive在判断连接失败后只会将连接丢弃。
4.23 说说端到端,点到点的区别
1、端到端
端到端通信是针对传输层来说的,传输层为网络中的主机提供端到端的通信。因为无论tcp还是udp协议,都要负责把上层交付的数据从发送端传输到接收端,不论其中间跨越多少节点。所以所谓端到端,就是从发送端到接收端。
端到端是一个网络连接,指的是在数据传输之前,在发送端与接收端之间为数
据的传输建立一条链路,链路建立以后,发送端就可以发送数据,直到数据发送完毕,接收端确认接收成功。 (即在数据传输之前,先为数据的传输开辟一条通道,然后在进行传输。从发送端发出数据到接收端接收完毕,结束。)
端到端通信建立在点到点通信的基础之上,它是由一段段的点到点通信信道构成的,是比点到点通信更高一级的通信方式,完成应用程序(进程)之间的通信。
端到端的优点:
链路建立之后,发送端知道接收端一定能收到,而且经过中间交换设备时不需要进行存储转发,因此传输延迟小。
端到端传输的缺点:
(1)直到接收端收到数据为止,发送端的设备一直要参与传输。如果整个传输的延迟很长,那么对发送端的设备造成很大的浪费。
(2)如果接收设备关机或故障,那么端到端传输不可能实现。
2、点到点
点到点通信是针对数据链路层或网络层来说的,因为数据链路层只负责直接相连的两个节点之间的通信,一个节点的数据链路层接受ip层数据并封装之后,就把数据帧从链路上发送到与其相邻的下一个节点。
点对点是基于MAC地址和或者IP地址,是指一个设备发数据给与该这边直接连接的其他设备,这台设备又在合适的时候将数据传递给与它相连的下一个设备,通过一台一台直接相连的设备把数据传递到接收端。
直接相连的节点对等实体的通信叫点到点通信。它只提供一台机器到另一台机器之间的通信,不会涉及到程序或进程的概念。同时点到点通信并不能保证数据传输的可靠性,也不能说明源主机与目的主机之间是哪两个进程在通信。由物理层、数据链路层和网络层组成的通信子网为网络环境中的主机提供点到点的服务。
点到点的优点:
(1)发送端设备送出数据后,它的任务已经完成,不需要参与整个传输过程,这样不会浪费发送端设备的资源。
(2)即使接收端设备关机或故障,点到点传输也可以采用存储转发技术进行缓冲。
点到点的缺点:
点到点传输的缺点是发送端发出数据后,不知道接收端能否收到或何时能收到数据。在一个网络系统的不同分层中,可能用到端到端传输,也可能用到点到点传输。如Internet网,IP及以下各层采用点到点传输,4层以上采用端到端传输。
4.24 说说浏览器从输入 URL 到展现页面的全过程
1、输入地址
2、浏览器查找域名的 IP 地址
3、浏览器向 web 服务器发送一个 HTTP 请求
4、服务器的永久重定向响应
6、服务器处理请求
7、服务器返回一个 HTTP 响应
8、浏览器显示 HTML
9、浏览器发送请求获取嵌入在 HTML 中的资源(如图片、音频、视频、CSS、JS等等)
4.25、简述 HTTP 和 HTTPS 的区别?
1、HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
2、HTTP与HTTPS的区别
https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
4.26说说 HTTP 中的 referer 头的作用
1、HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
2、防盗链。假如在www.google.com里有一个www.baidu.com链接,那么点击进入这个www.baidu.com,它的header信息里就有:Referer= http://www.google.com,即只允许我本身的网站访问本身的图片服务器,假如域是www.google.com
那么图片服务器每次取到Referer来判断一下域名是不是 www.google.com ,
如果是就继续访问,不是就拦截。
将这个http请求发给服务器后,如果服务器要求必须是某个地址或者某几个地址才能访问,而你发送的referer不符合他的要求,就会拦截或者跳转到他要求的地址,然后再通过这个地址进行访问。
3、防止恶意请求
比如静态请求是.html 结尾的,动态请求是.shtml ,那么由此可以这么用,所有的*.shtml 请求,必须Referer为我自己的网站。
4、空Referer
定义:Referer头部的内容为空,或者,一个HTTP请求中根本不包含Referer头部(一个请求并不由链接触发产生的),直接在浏览器的地址栏中输入一个资源的URL地址,那么这种请求是不会包含Referer字段的,因为这是一个"凭空产生"的HTTP请求,并不是从一个地方链接过去的。
那么在防盗链设置中,允许空Referer和不允许空Referer有什么区别?
允许Referer为空,意味着允许通过浏览器直接访问。
5、防御CSRF
比对HTTP 请求的来源地址,如果Referer中的地址是安全可信任的地址,那么就放行
4.27 说说 HTTP 的方法有哪些
GET: 用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器
POST:用于传输信息给服务器,主要功能与GET方法类似,但一般推荐使用POST方式。
PUT: 传输文件,报文主体中包含文件内容,保存到对应URI位置。
HEAD: 获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效。
DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件。
OPTIONS:查询相应URI支持的HTTP方法
vector和list的区别:
从内存的角度说明
vector在内存中是一段连续的存储空间。
list的内存空间是分散的,通过指针连接起来
4.28简述 HTTP 1.0,1.1,2.0 的主要区别 (了解)
http/1.0 :
- 默认不支持长连接,需要设置keep-alive参数指定
- 强缓存expired、协商缓存last-modified\if-modified-since 有一定的缺陷
http/1.1:
- 默认长连接(keep-alive),http请求可以复用Tcp连接,但是同一时间只能对应一个http请求(http请
求在一个Tcp中是串行的) - 增加了强缓存cache-control、协商缓存etag\if-none-match 是对http/1 缓存的优化
http/2.0 :
- 多路复用,一个Tcp中多个http请求是并行的 (雪碧图、多域名散列等优化手段http/2中将变得多余)
- 二进制格式编码传输
- 使用HPACK算法做header压缩
- 服务端推送
4.29 说说 HTTP 常见的响应状态码及其含义
200 : 从状态码发出的请求被服务器正常处理。
204 : 服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分【即没有内容】。
206 : 部分的内容(如:客户端进行了范围请求,但是服务器成功执行了这部分的干请求)。
301 : 跳转,代表永久性重定向(请求的资源已被分配了新的URI,以后已使用资源,现在设置了URI)。
302 : 临时性重定向(请求的资源已经分配了新的URI,希望用户本次能够使用新的URI来进行访问)。
303 : 由于请求对应的资源存在的另一个URI(因使用get方法,定向获取请求的资源)。
304 : 客户端发送附带条件的请求时,服务器端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回了 304。
307 : 临时重定向【该状态码与302有着相同的含义】。
400 : 请求报文中存在语法错误(当错误方式时,需修改请求的内容后,再次发送请求)。
401 : 发送的请求需要有通过HTTP认证的认证信息。
403 : 对请求资源的访问被服务器拒绝了。
404 : 服务器上无法找到请求的资源。
500 : 服务器端在执行请求时发生了错误。
503 : 服务器暂时处于超负载或者是正在进行停机维护,现在无法处理请求。
1XX : 信息类状态码(表示接收请求状态处理)
2XX : 成功状态码(表示请求正常处理完毕)
3XX : 重定向(表示需要进行附加操作,已完成请求)
4XX : 客户端错误(表示服务器无法处理请求)
5XX : 服务器错误状态码(表示服务器处理请求的时候出错)
4.30说说 GET请求和 POST 请求的区别
GET 和 POST 是 HTTP 协议中最常用的两种请求方法,它们在数据传输方式、安全性、使用场景等方面有显著区别。以下是它们的核心区别:
- 数据传输位置
GET POST
数据附加在 URL 后,格式为 ?key1=value1&key2=value2 数据放在 请求体(Body) 中
示例:/api/user?id=123 示例:/api/user(Body: {"id":123})
关键区别:
- GET 请求的参数在地址栏可见,POST 不可见(对用户更隐蔽)。
- 数据长度限制
GET POST
受 URL 长度限制(浏览器通常限制为 2048-8192 字符) 理论上 无限制(服务器可配置限制)
关键区别:
- GET 适合传输少量数据(如搜索关键词),POST 适合大数据(如文件上传)。
- 安全性
GET POST
参数暴露在 URL 中,可能被浏览器缓存、历史记录保存 数据在 Body 中,安全性更高(但仍是明文,HTTPS 才真正安全)
关键区别:
- 敏感数据(如密码)绝对不要用 GET,优先用 POST + HTTPS。
- 幂等性与缓存
GET POST
幂等(多次请求结果相同) 非幂等(可能修改服务器状态)
可被浏览器/代理缓存 默认不缓存
关键区别:
- GET 适合查询操作(如刷新页面不会重复提交),POST 适合提交操作(如支付)。
- 使用场景
GET POST
获取数据(如搜索、分页) 提交数据(如登录、表单提交)
数据可书签保存(URL 完整) 数据不可书签保存
示例:/search?q=keyword 示例:/login(Body 传用户名密码)
总结:如何选择?
- 用 GET 当:
- 只需读取数据(如搜索、加载页面)。
- 参数少且非敏感。
- 需要缓存或书签功能。
- 用 POST 当:
- 需修改服务器数据(如提交表单)。
- 传输大数据(如文件)。
- 参数敏感(如密码)。
- 永远记住:
- GET 参数在 URL 中可见,POST 更隐蔽(但都不是绝对安全,必须用 HTTPS)。
- RESTful API 设计时,严格遵循语义化(GET 查、POST 增)。
4.31 谈谈对cookie和session的理解
cookie 和 Session 是 Web 开发中用于维护用户状态的两种关键技术,它们既有协作关系,又有本质区别。以下是它们的核心对比:
- 存储位置不同
Cookie Session
客户端存储(浏览器本地) 服务端存储(服务器内存/数据库)
以文本文件形式保存在用户设备 数据存储在服务器,客户端只保存 Session ID
示例:
- Cookie:浏览器保存 user_token=abc123
- Session:服务器内存中存储 {session_id: "abc123", user_id: 1001}
- 安全性对比
Cookie Session
较低(可直接查看/篡改) 较高(敏感数据在服务端)
需手动设置 HttpOnly、Secure 提升安全 默认更安全
- 生命周期管理
Cookie Session
通过 Expires/Max-Age 设置过期时间 通常随会话结束过期(或服务器主动销毁)
可长期保留(如"记住我"功能) 一般较短(用户关闭浏览器即失效)
- 存储容量限制
Cookie Session
单个域名下通常 4KB 左右 理论上 无限制(取决于服务器配置)
浏览器对 Cookie 数量也有限制 适合存储大量用户数据
-
工作关系(协作流程)
-
用户首次访问:
- 服务端创建 Session 并生成唯一 Session ID
- 通过 Set-Cookie 头将 Session ID 发给浏览器保存
-
后续请求:
- 浏览器自动携带 Cookie(含 Session ID)
- 服务端通过 Session ID 查找对应用户数据
4.32HTTPS 连接建立的核心流程
-
证书传递与验证阶段
-
服务端发送证书
- 当客户端(浏览器)连接到服务器的 443 端口时,服务器会立即将自己的 数字证书(包含公钥、域名、有效期等信息)发送给客户端。
-
客户端验证证书
- 查找颁发机构:浏览器检查证书是否由内置的 受信任根证书机构(CA) 签发(如 DigiCert、Let's Encrypt)。
- 若证书机构未知,浏览器会警告用户(如 Chrome 的 "您的连接不是私密连接")。
- 验证签名:用 CA 的公钥解密证书签名,验证证书未被篡改。
- 检查域名和有效期:确保证书中的域名与当前访问的域名完全匹配,且证书未过期。
- 查找颁发机构:浏览器检查证书是否由内置的 受信任根证书机构(CA) 签发(如 DigiCert、Let's Encrypt)。
-
信任链验证
- 浏览器会向上追溯证书链(中级 CA → 根 CA),直到找到受信任的根证书。
-
密钥交换与加密通信阶段
-
生成会话密钥
- 客户端生成一个 随机数(Pre-Master Secret),用服务器的公钥加密后发送给服务器。
-
密钥协商完成
- 服务器用私钥解密获取随机数,双方根据该随机数生成相同的 对称加密密钥(Session Key)。
-
加密通信开始
- 后续所有数据传输均使用该对称密钥加密(如 AES 算法),保障数据机密性和完整性。
完整流程示意图