
00 计算机网络知识点归纳 笔记
计算机网络知识点归纳
网络分层模型
介绍一下 OSI 七层协议,各层协议都有哪些?
答:
OSI参考模型共有7层,从上到下分别是:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层- 应用层的协议有:
HTTP、HTTPS - 传输层的协议有:
TCP和UDP - 网络层的协议有:
IP、ICMP、ARP
- 应用层的协议有:
- 我认为,网络分层的好处是:对各个层之间进行了解耦,层一层之间不会产生关联性,比如:我们应用层的
HTTP协议,从HTTP1.1升级到HTTP2.0的时候,并不会对传输层、网络层等有影响,或者网络层的IPv4协议升级为IPv6协议的时候,也不会影响应用层、传输层 - 不过,
OSI参考模型只是理论模型,实际上因特网中的网络模型是使用了TCP/IP网络模型,它对OSI参考模型做了简化,把 应用层、表示层、会话层 统一成了 应用层,数据链路层 和 物理层 统一成了 网络接口层
补充:

OSI的 7 层模型从上到下依次为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层- 应用层:负责直接与 软件应用程序 交互以提供所需的通信功能,并且它 与最终用户最接近
- 应用层的功能:通常包括 验证通信伙伴 和 资源的可用性 以支持任何数据传输。该层还定义了用于最终应用程序的协议,例如:域名系统(
DNS)、文件传输协议(FTP)、超文本传输协议(HTTP)、Internet消息访问协议(IMAP)、邮局协议(POP)、简单邮件传输协议(SMTP)、简单网络管理协议(SNMP)和Telnet(终端仿真)
- 应用层的功能:通常包括 验证通信伙伴 和 资源的可用性 以支持任何数据传输。该层还定义了用于最终应用程序的协议,例如:域名系统(
- 表示层:表示层提供各种用于应用层数据的编码和转换功能,确保一个系统的应用层发送的数据能被另个系统的应用层识别,如:数据转换,压缩和加密,解密
- 表示层可以 处理任何所需的数据格式或代码转换
- 例如:将扩展 二进制编码 的 十进制交换码(
EBCDIC)编码的文本文件 转换为 美国信息交换标准码(ASCII)编码的文本文件 - 表示层也 可用于数据压缩和加密
- 例如:视频呼叫将在传输过程中被压缩。以便可以更快地传输,并且数据将在接收方恢复。对于具有较高安全性要求的数据(例如:包含你的密码的短信),将在此层进行加密
- 会话层:会话层控制计算机之间的对话(连接)它建立,管理,维护并最终终止本地和远程应用程序之间的连接
- 会话层软件 还 处理 身份验证 和 授权功能。会话层通常在使用远程过程调用的应用程序环境中明确实现
- 传输层:负责两个设备间的 端 到 端 通信
- 包括:从会话层提取数据,将数据分解为多个数据,然后再发送到网络层
- 传输层还负责进行 流量控制 和 错误控制。流量控制 用于 确定最佳传输速度,避免发送方发送速率过快导致接收方接收不过来的情况。传输层还会确保接收数据的完整性(如果不完整,则请求重新传输)来对接收端进行错误控制。传输层包含
TCP和UDP协议
- 网络层:网络层通过 逻辑寻址 和 交换功能 处理 数据包路由
- 这一层:实现 不同网络 之间的 数据传输。它进一步将网段或数据报分解成更小的数据包,并使用
IP地址找到通往最终目的地的最佳路由。这一过程被称为 路由选择 - 网络是可以连接许多 节点 的介质。每个节点都有一个地址。当一个节点需要将消息传输到其他节点时,它仅能提供 消息的内容 和 目标节点的地址,则网络将找到将消息传递到目标节点的方法,并可能通过其他节点进行路由。如果消息太长,网络可能会在一个节点上将其拆分为多个段,分别发送它们,然后在另一节点上重新组合片段
- 这一层:实现 不同网络 之间的 数据传输。它进一步将网段或数据报分解成更小的数据包,并使用
- 数据链路层:数据链路层提供 节点 到 节点 的传输,即:两个直接连接的节点之间的链接
- 这一层允许在 同一网络 的 设备 之间传输数据。数据包 被分解成 帧,这些帧被限制在 局域网 内
- 它以 帧 的形式处理 数据的打包 和 拆包。它定义了在两个物理连接的设备之间建立和终止连接的协议,例如:点对点协议(
PPP) - 数据链路层通常分为两个子层:媒体访问控制(
MAC)层和 逻辑链路控制(LLC)层。MAC层负责控制网络中的设备如何访问媒体以及允许传输数据。LLC层负责标识和封装网络层协议,并控制错误检查和帧同步
- 物理层:物理层定义了数据连接的物理规格
- 例如:连接器的插针布局,电缆的工作电压,光纤电缆规格以及无线设备的频率。它负责物理介质中非结构化原始数据的发送和接收
详细链接:面试官:我们为什么需要 7 层 OSI 网络模型?、什么是 OSI 模型? | Cloudflare
TCP/IP 网络模型有哪几层?
答:
TCP/IP网络模型主要有 四 层,从上到下分别是:应用层、传输层、网络层、网络接口层- 应用层:负责为 应用软件 提供 网络服务
- 例如:
HTTP、HTTPS、DNS等协议
- 例如:
- 传输层:负责为 应用程序层 提供 数据传输服务
- 传输层协议 主要有
TCP和UDPTCP是 可靠 传输协议UDP是 不可靠 的传输协议
- 传输层协议 主要有
- 网络层:负责主机 寻址,打包 和 路由 功能
- 网络层的核心协议是:
IP、ARP、ICMP等协议IP协议负责寻址和路由ARP协议负责获取MAC地址ICMP负责提供诊断功能并报告错误
- 网络层的核心协议是:
- 网络接口层:负责为 网络层提供「链路级别」传输的服务,负责 在 以太网、
WiFi这样的底层网络上发送原始数据包- 工作在 网卡 这个层次,使用
MAC地址来标识网络上的设备
- 工作在 网卡 这个层次,使用
补充:

-
TCP/IP网络模型有两种说法, 有的说 五 层TCP/IP网络模型,有的说 四 层TCP/IP网络模型- 四层
TCP/IP网络模型是:应用层、传输层、网络层、网络接口层 - 五层
TCP/IP网络模型是:应用层、传输层、网络层、数据链路层、物理层
- 四层
-
TCP/IP网络通常是由上到下分成 4 层,分别是:应用层,传输层,网络层 和 网络接口层 -
应用层:
TCP/IP模型的应用程序层使应用程序能够访问其他层的服务,并定义了应用程序用来交换数据的协议- 最熟悉的应用层协议包括:
HTTP、FTP、SMTP、Telnet、DNS、SNMP和 路由信息协议(RIP)
- 最熟悉的应用层协议包括:
-
传输层:传输层负责 为 应用程序层 提供 会话 和 数据通信服务

- 该层的核心协议是
TCP和UDPTCP提供 一对一,面向连接 的 可靠通信服务。它负责对发送的数据包进行排序和确认,并恢复传输中丢失的数据包UDP提供 一对一 或 一对多 的 无连接,不可靠 的通信服务。当要传输的数据量较小时(例如,该数据可以放入单个数据包中),通常使用UDP
- 该层的核心协议是
-
网络层:网络层 负责 主机寻址,打包 和 路由功能

- 网络层负责 将 数据 从 一个设备 传输到 另一个设备
- 网络层的核心协议:
IP、地址解析协议(ARP)、Internet控制消息协议(ICMP)和Internet组管理协议(IGMP)IP是可路由协议,负责IP寻址,路由以及数据包的分段和重组- 将
IP地址分成两种意义:- 一个是 网络号,负责标识该
IP地址是属于哪个「子网」的IP地址与 子网掩码 按位 与 运算
- 一个是 主机号,负责标识同一「子网」下的不同主机
IP地址与 子网掩码取反后 按位 与 运算
- 一个是 网络号,负责标识该
- 将
ARP负责发现网络访问层地址,例如:与给定Internet层访问关联的硬件地址- 由于
IP数据包传递失败,ICMP负责提供诊断功能并报告错误 IGMP负责IP多播组的管理。IP在此层中将标头添加到数据包中,称为IP地址。现在既有IPv4(32位)地址又有IPv6(128位)地址
-
网络接口层:网络接口层 负责将
TCP/IP数据包放在网络介质上,并从网络介质上接收TCP/IP数据包TCP/IP被设计为 独立于网络访问方法,帧格式 和 介质。换句话说,它独立于任何特定的网络技术。这样,TCP/IP可以用于连接不同的网络类型,例如:以太网,令牌环,X.25,帧中继和异步传输模式(ATM)

详细链接:2.1 TCP/IP 网络模型有哪几层? | 小林coding
IP 协议和 TCP 协议属于哪一层?
答:
IP 协议属于 网络层,TCP 协议属于 传输层
网络为什么要分层?
答:
- 分层的目的是 为了降低耦合,各层相互独立之后,上层可以不关心下层的实现,只关心下层提供的接口服务,有利于排查网络问题,能更精细定位问题所在哪一层
- 分层之后层与层之间不会产生关联性,不会因为某个层的改动,影响了其他层
- 比如:应用层的
HTTP协议,从HTTP1.1升级到HTTP2.0的时候,并不会对 传输层、网络层 等有影响,或者网络层的IPv4协议升级为IPv6协议的时候,也不会影响 应用层、传输层
- 比如:应用层的
补充:
- 分层的好处:
- 各层之间是 独立的
- 某一层 并不需要知道它 下一层 是如何实现的,而仅仅需要知道该层通过层间的接口所提供的服务。由于每一层只实现一种相对独立的功能,因而可以将一个难以处理的复杂问题分解为若干个较容易处理的更小问题,这样,整个问题的复杂度就下降了
- 灵活性好
- 当任何一层发生变化时,只要层间接口关系保持不变,则在这层以上或以下各层均不受影响此外,对某一层提供的服务还可以进行修改。当某层提供的服务不再需要时,甚至可以将这层取消
- 各层之间是 独立的
键入网址场景问题
输入网址后,期间发生了什么?
答:
在浏览器输入网址后:
-
浏览器会先解析
URL,解析出 域名、资源路径、端口 等信息,然后构造HTTP请求报文
-
接着进行 域名 解析,将 域名解析 为
IP地址,会先查 系统缓存 是否 域名信息,如果有就返回IP地址,没有就会查看本地系统host文件有没有域名信息,如果有就返回IP地址,如果没有就去查本地DNS服务器,如果本地DNS服务器缓存中有域名信息,就返回IP地址,否则本地DNS服务器分别去 根域名服务器 → 顶级域名服务器 → 权威域名服务器询问,最后拿着返回的IP交给浏览器
-
由于
HTTP是基于TCP传输的,所以 在发送HTTP请求前,要进行 三次握手,在客户端发送第一次握手的时候,TCP头部会填上SYN标记位,同时填上 目标端口 和 源端口 的信息。源端口 是 浏览器随机生成的,目标端口要看是HTTP还是HTTPS,如果是HTTP默认目标端口是 80,如果是HTTPS默认是 443 -
然后到 网络层,会加上
IP头,同时填上 目标IP地址 和 源IP地址 -
然后到 数据链路层,会通过
ARP协议,获取路由器的MAC地址,然后会加上MAC头,填上 目标MAC地址 和 源MAC地址 -
然后到 物理层 之后,直接把 数据包,转发给 路由器,路由器再通过下一跳,最终找到 目标服务器,然后目标服务器收到客户的
SYN报文后,会响应第二次握手 -
当双方都 完成 三次握手 后,如果是
HTTP协议,客户端就会将HTTP请求就会发送给目标服务器;如果是HTTPS协议,客户端 还要和 服务端 进行TLS四次握手之后,客户端才会将HTTP报文发送给目标服务器 -
目标服务器收到
HTTP请求消息后,就返回HTTP响应消息,浏览器会对响应消息进行解析渲染,呈现给用户
补充:
关键要讲出输入网址后涉及的每一个网络协议的工作原理和作用:
HTTP/HTTPS协议 →DNS协议 →TCP协议 →IP协议 →ARP协议

详细链接:2.2 键入网址到网页显示,期间发生了什么? | 小林coding
DNS 是如何解析的?属于哪一层的协议?
答:
DNS属于 应用层 的协议- 客户端在进行
DNS解析之前,会先查看 浏览器 和 操作系统 是否有缓存域名对应的IP地址,没有就会查看本地系统host文件有没有域名信息,如果有就返回IP地址 - 如果没有就会向本地
DNS服务器发出查询请求,如果没有接着本地DNS向 根DNS发送查询请求,根DNS服务器收到请求后会返回顶级域名服务器的IP地址,然后本地DNS服务器再向顶级域名服务器发出查询请求,顶级DNS服务器收到请求后会返回权威域名服务器的IP地址,然后本地DNS服务器再向 权威域名服务器 发出查询请求,权威域名服务器 收到请求后,就会返回域名对应的IP地址了,最后本地DNS服务器返回查询结果给客户端,同时本地域名服务器把返回的结果保存到缓存,以备下一次使用。客户端通过这个IP地址就可以访问目标Web服务器了。到这里,DNS查询的整个过程就结束了
- 客户端在进行
补充:

详细链接:公网域名解析_云解析服务 DNS_华为云
DNS域名解析使用的什么协议?
答:
- 在
DNS中,域名解析 请求 和 响应 都是基于UDP进行传输的 UDP是一种 无连接 的 传输层协议,它提供了一种简单的传输机制,适用于对 实时性要求较高 的应用场景。DNS使用UDP协议进行域名解析是因为 域名解析 通常是 短小而频繁 的请求,UDP的无连接特性可以减少建立和断开连接的开销,并提高解析的效率(UDP协议以及UDP相较于TCP的优点)UDP对于TCP的缺点是没办法保证数据的可靠传输,针对这个缺陷,可以在应用层实现一个超时重传机制,如果域名解析请求在一定时间内没收到响应,那么就重发域名解析请求(UDP不保证可靠性的缺点)
详细链接:DNS 协议是什么?完整查询过程?为什么选择使用 UDP 协议发起 DNS 查询?> 你可能了解 DNS 协议是什么?那 - 掘金
输入域名如何知道端口的?
答:
HTTP 默认端口是 80,HTTPS 默认端口是 443,如果用户指定了端口,比如:域名:8080,这时候就会使用8080 作为目标端口
补充:
http://baidu.com/,默认端口是 80https://baidu.com/,默认端口是 443http://baidu.com:8080/,指定的端口是 8080
详细链接:[11 你能写出正确的网址吗?](https://learn.lianglianglee.com/专栏/透视HTTP协议/11 你能写出正确的网址吗?.md)
客户端向服务端的 IP 地址发送数据,服务端如何确定应该把数据传递给谁?
答:
服务端的应用会监听端口,协议栈会通过端口来区分不同应用的数据
补充:
每个传输层协议(如:TCP 和 UDP)都使用 端口号 来标识不同的应用程序或服务,服务端 通过 监听 特定的端口号来接收来自客户端的数据
现在很多网站都要求使用 https,假设我们输入一个 http 网址,网站是如何实现由 http 跳转到 https 的?
答:
- 服务器网关收到
http请求后,给客户端一个http响应,状态码为301(永久重定向) - 浏览器收到 重定向 响应后,自动向服务器发起一个新的
HTTPS请求(默认端口443)
补充:
网站实现由 HTTP 跳转到 HTTPS 的过程通常涉及 服务器端的配置,以确保用户访问的是 加密 的连接。以下是 nginx 服务器端配置方法,可以在虚拟主机的配置文件中添加以下代码来实现重定向:
1 | server { |
网络传输场景问题
如果浏览器没有显示页面有哪些原因?
答:
最直接的办法就是 抓包,排查的思路大概有:
- 先确定是 服务端 的问题,还是 客户端 的问题
- 先在 客户端 确认浏览器是否可以访问其他网站,如果不可以,说明客户端网络自身的问题,然后检查 客户端 网络配置(连接
wifi正不正常,有没有插网线) - 如果可以正常其他网页,说明 客户端 网络是可以正常上网的
- 先在 客户端 确认浏览器是否可以访问其他网站,如果不可以,说明客户端网络自身的问题,然后检查 客户端 网络配置(连接
- 如果 客户端 网络没问题,就抓包确认
DNS是否解析出了IP地址,如果没有解析出来,说明域名写错了,如果解析出了IP地址,抓包确认有没有和服务端建立三次握手:- 如果没有成功建立三次握手,需要在服务端通过
ps确认server进程是否启动了,以及通过netstate命令确认是否监听了端口 - 如果能成功建立三次握手,并且发出了
HTTP请求,但是就是没有显示页面,可以查看服务端返回的响应码:- 如果是
404错误码,检查输入的url是否正确 - 如果是
500,说明服务器此时有问题,这时候就需要去服务器排查日志了 - 如果是
200,可以在浏览器按F12输出前端控制台,看看前端代码有问题导致浏览器没有渲染出页面
- 如果是
- 如果没有成功建立三次握手,需要在服务端通过
- 如果 客户端 网络是正常的,但是访问速度很慢,导致很久才显示出来。可以通过
ping去确认网络延迟是否正常,如果耗时很严重,可以排查服务器的流量是不是很大,导致超过了带宽上限,产生了丢包的问题。如果网络是正常的,可能要排查接口为什么处理这么久,这里有可能是慢sql导致的
总之就 是一层一层有没有插网线,网络配置是否正确、DNS 有没有解析出 IP 地址、TCP 有没有三次握手、HTTP 返回的响应码是什么
详细链接:字节一面:网站显示不出来,怎么排查?
服务器ping不通但是http能请求成功,会出现这种情况吗?
答:
- 会的
- 因为
ping和http使用的协议是不一样的,ping是基于网络层的ICMP协议,而http是基于传输层的TCP协议的,有可能服务器的防火墙禁止ICMP协议,但是TCP协议没有禁止,就会出现服务器ping不通,但是http能请求现象
补充:
- 主要是
ping和http底层的协议区别
详细链接:5.2 ping 的工作原理 | 小林coding
客户端 TCP 连接一个不存在的 IP 地址的服务端会发生什么?(cold)
答:
- 分情况讨论:
- 如果访问的
IP地址是局域网内的,客户端的内核在发ARP请求的时候,广播询问这个目标IP地址是谁的,由于网络中不存在该目标IP地址,所以没有设备应答客户端的ARP请求,这时候就会卡在ARP协议,客户端的SYN报文是发送不出去的 - 如果访问的
IP地址不是局域网的,客户端会先将SYN报文发给路由器,然后路由器会继续转发,由于目标IP地址是不存在的,该SYN报文会在网络中消亡,因此客户端是不会收到对SYN报文的确认报文的,接着客户端会触发超时重传,重传SYN报文,直到重传的次数达到最大次数后,客户端的连接就会被释放
- 如果访问的
详细链接:字节面试:连接一个不存在的 IP 地址,会发生什么?
客户端 TCP 连接一个 IP 地址存在但是端口不存在的服务端会发生什么?(cold)
答:
端口不存在的话,代表服务端没有监听这个端口,服务端在收到客户端的 SYN 报文后,服务端会回 RST 报文,客户端收到 RST 报文后,会断开连接
补充:

- 如果客户端访问了没有被服务端监听的端口的话,服务端会回
RST报文
详细链接:4.19 服务端没有 listen,客户端发起连接建立,会发生什么? | 小林coding
客户端 UDP 发送一个 IP 地址存在但是端口不存在报文会发生什么?(cold)
答:
服务端会回 ICMP 报文,报告端口不可达
补充:
UDP 没有 RST 报文,所以如果端口不存在,这时候会在网络层通过 ICMP 协议,报告端口不可达的消息给客户端

详细链接:关于UDP接收icmp端口不可达(port unreachable)_icmp port unreachable-CSDN博客
HTTP
HTTP 协议的特点是什么?
答:
HTTP具有简单、灵活可扩展、无状态等特点,是一种广泛应用于Web通信的协议- 基于文本:
HTTP的消息是以 文本形式 传输,易于阅读和调试 - 可扩展性:
HTTP协议本身不限制数据的内容和格式,可以通过 扩展头部、方法 等来支持新的功能 - 灵活性:
HTTP支持不同的数据格式(如:HTML、JSON、XML等),适用于多种应用场景 - 请求应答模式:
HTTP协议使用的是 请求 - 应答 通信模式,请求方先发起连接和请求,是主动的,而应答方只有在收到请求后才能答复,是被动的,如果没有请求时不会有任何动作 - 无状态:
HTTP每个请求之间相互独立,服务器不会保留之前请求的状态信息,需要通过其他手段(如:Cookies、Session)来维护状态
- 基于文本:
补充:
HTTP是 灵活可扩展 的,可以任意添加头字段实现任意功能HTTP是可靠传输协议,基于TCP/IP协议 “尽量” 保证数据的送达HTTP是应用层协议,比FTP、SSH等更通用功能更多,能够传输任意数据HTTP使用了 请求 - 应答 模式,客户端主动发起请求,服务器被动回复请求HTTP本质上是无状态的,每个请求都是互相独立、毫无关联的,协议不要求客户端或服务器记录请求相关的信息。
详细链接:[13 HTTP有哪些特点?](https://learn.lianglianglee.com/专栏/透视HTTP协议/13 HTTP有哪些特点?.md)
HTTP 报文格式?怎么分割的?
答:
HTTP报文格式分为 请求行、请求头、请求体 三个部分:- 请求行 是 请求或响应的基本信息,比如:请求方法、
URL、HTTP版本信息 - 请求头 是 用
key-value形式更详细地说明报文,比如:Host字段、Connection字段、Content-Length字段 - 请求体 是 实际传输的数据,比如:文本数据、图片数据
- 请求行 是 请求或响应的基本信息,比如:请求方法、
- 请求行 和 请求头 是通过
\r\n分割的,请求头 和 请求体 之间是通过 空白行 分割的,也就是 两个连续的\r\n
补充:
HTTP报文格式分为 请求行、请求头、请求体 三个部分- 请求行的内容是
HTTP方法、URL、HTTP版本号,请求行里的字段之间是通过 空格 分割,请求行 和 请求头 是通过\r\n分割的 - 请求头 的 内容 是 多个键值对字段的集合,键 和 值 通过 冒号 分割,每个字段之间通过
\r\n分割 - 请求体 的内容是 实体数据,请求头 和 请求体 之间是通过 空白行 分割的,即:两个连续的
\r\n(回车符 + 换行符)
- 请求行的内容是

详细链接:[09 HTTP报文是什么样子的?](https://learn.lianglianglee.com/专栏/透视HTTP协议/09 HTTP报文是什么样子的?.md)
HTTP 默认的端口是什么?
答:
80 端口
补充:
端口 是 TCP 的概念,针对 HTTP 协议,服务端默认是监听 80 端口,针对 HTTPS 协议,服务端默认是监听 443 端口
详细链接:HTTP、HTTPS常用的默认端口号 - 景寓6号 - 博客园
HTTP 有什么方法?
答:
- 我了解到
HTTP方法的有GET、POST、PUT、HEAD、DELETE这些方法,其中:GET方法是用来 请求从服务器获取资源的HEAD方法和GET方法类似,也是请求从服务器获取资源,但与GET请求不同的是,服务器不会返回请求的实体数据,只会传回响应头,也就是获取的是资源的 “元信息”POST方法是 用来向服务端提交数据,数据就放在报文的body里PUT方法和POST类似,也可以向服务器提交数据,区别在于POST是 “新增数据”,PUT是 “更新数据”DELETE方法是用来 删除资源
- 在项目开发中,用的比较多是
GET和POST请求
补充:
目前 HTTP/1.1规定的八种方法,单词必须是 大写 的形式

详细链接:[10 应该如何理解请求方法?](https://learn.lianglianglee.com/专栏/透视HTTP协议/10 应该如何理解请求方法?.md)
分析一下哪些 HTTP 方法是安全或者幂等的?
答:
GET和HEAD方法是 安全且幂等 的,因为它们是 只读 操作,只要开发者遵循规范要求的去处理请求,无论GET和HEAD操作多少次,服务器上的数据都是安全的POST/PUT/DELETE这些方法都会 增上改服务器上的资源,所以是 不安全 的DELETE和PUT方法是 幂等 的,因为DELETE是 删除资源,多次删除,效果都是资源不存在,所以也是 幂等 的,另一个PUT是 更新数据,多次更新数据,结果都一样,所以是 幂等 的- 但是
POST是不幂等的,因为多次POST请求,会创建多个资源,所以 不是幂等 的
补充:
- 在
HTTP协议里:- 所谓的 “安全” 是指:请求方法不会 “破坏” 服务器上的资源,即:不会对服务器上的资源造成实质的修改
- 所谓的 “幂等” 实际上是一个数学用语,被借用到了
HTTP协议里,意思是:多次执行相同的操作,结果也都是相同的,即:多次 “幂” 后结果 “相等”
- 分类:
- 安全的方法:
GET/HEAD - 不安全的方法:
POST/DELETE/PUT - 幂等的方法:
GET/HEAD/DELETE/PUT - 不幂等的方法:
POST
- 安全的方法:
GET 和 POST 请求的区别?
答:
GET请求是 从服务器获取资源,POST请求是 向服务器提交数据GET方法是 只读 操作,所以是 安全且幂等 的,而POST方法会修改服务器上的资源,并且多次POST请求,会创建多个资源,所以 不是安全,也不是幂等 的GET请求的请求参数放在URL中的查询字符串中,浏览器对URL长度限制,所以GET请求的请求参数会有长度限制,而POST请求的请求参数是放在请求体中,POST请求的请求参数长度没有限制
补充:
从几个角度分析:
- 两个请求的语义上的区别
- 两个请求的是否是安全且幂等的?
- 请求参数的区别
GET 请求一定是安全且幂等的吗?
答:
不一定,要看实际的 GET 请求,如果 开发者遵循了规范去处理请求,也就是 GET 请求的实现是获取资源,那么就是安全且幂等的,但是 如果开发者处理 GET 请求的方式是 新增数据,这时候 GET 请求就 不是安全且幂等的
HTTP 有什么状态码?
答:
HTTP 状态共有 5 类:
- 数字
1开头的状态码:表示目前是 协议处理的中间状态,还需要后续操作,比如:客户端请求服务端从HTTP切换为WebSocket通信的时候,服务端如果同意切换,就会回101状态码 - 数字
2开头的状态码:表示 服务器收到并成功处理了客户端的请求,比如:200状态码是代表 服务端 成功响应了 客户端 的请求 - 数字
3开头的状态码:表示 服务端的资源发生了变动,需要进行 重定向 了,比如:301是代表永久重定向、302代表临时重定向 - 数字
4开头的状态码:是 客户端错误,表示客户端发送的请求报文有误,服务器无法处理,比如:404状态码表示资源在本服务器上未找到 - 数字
5开头的状态码:是 服务端错误,服务器在处理时内部发生了错误,比如:502状态码是nginx服务器作为代理时返回的错误码,表示nginx服务器自身工作正常,但是访问后端服务器时发生了错误,具体的错误需要去排查后端服务器
补充:
100类状态码属于 提示信息,是协议处理中的一种中间状态,实际用到的比较少- “
101 Switching Protocols”:请求者已要求服务器切换协议,服务器已确认并准备切换- 它的意思是客户端使用
Upgrade头字段,要求在HTTP协议的基础上改成其他的协议继续通信,比如:WebSocket。而如果服务器也同意变更协议,就会发送状态码101,但这之后的数据传输就不会再使用HTTP了
- 它的意思是客户端使用
- “
200类状态码表示 服务器成功处理了客户端的请求- “
200 OK”是 最常见的成功状态码:表示一切正常,服务器如客户端所期望的那样返回了处理结果,如果是非HEAD请求,通常在响应头后都会有body数据 - “
204 No Content” 是 另一个很常见的成功状态码,它的含义与 “200 OK” 基本相同,但响应头后没有body数据。所以对于Web服务器来说,正确地区分200和204是很必要的 - “
206 Partial Content” 是HTTP分块下载或断点续传的基础,在客户端发送 “ 范围请求 ”、要求获取资源的部分数据时出现,它与200一样,也是服务器成功处理了请求,但body里的数据不是资源的全部,而是其中的一部分
- “
300类状态码表示 客户端请求的资源发生了变动,需要客户端用新的URL重新发送请求获取资源,也就是重定向- “
301 Moved Permanently”:代表 永久性的重定向,值得注意的是,这种重定向跳转,从严格意义来讲不是服务器跳转,而是客户端跳转的。这个 “ 跳 ” 的动作是服务器是通过回传状态码301来下达给客户端的,让客户端完成跳转 - “
302 Found”:代表 临时跳转。例如:URL地址 A 可以向URL地址 B 上跳转,但这并不是永久性的,在经过一段时间后,URL地址 A 还可能向URL地址 C 上跳转 - “
304 Not Modified”:服务器通过返回状态码304可以告诉客户端请求资源成功,但是这个资源不是由服务器提供返回给客户端的,而是客户端本地浏览器缓存中就有的这个资源,因为可以从缓存中获取这个资源,从而节省传输的开销
- “
400类状态码表示 客户端发送的报文有误,服务器无法处理- “
400 Bad Request”:表示 请求报文有错误,但具体是数据格式错误、缺少请求头还是URI超长它没有明确说,只是一个笼统的错误,客户端看到400只会是 “ 一头雾水 ”、“不知所措” - “
403 Forbidden”:代表 请求的服务器资源权限不够,也就是没有权限去访问服务器的资源,或者请求的IP地址被封掉了 - “
404 Not Found”:代表 服务器上没有该资源,或者说服务器找不到客户端请求的资源,是最常见的请求错误码
- “
500类状态码表示 客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码- “
500 Internal Server Error”:代表 服务器程序错误,也就是说请求的网页程序本身报错了。在服务器端的网页程序出错。由于现在的浏览器都会对状态码500做一定的处理,所以在一般情况下会返回一个定制的错误页面 - “
501 Not Implemented”:服务器不具备完成请求的功能。 例如:服务器无法识别请求方法时可能会返回此代码。 - “
502 Bad Gateway”:通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误 - “
503 Service Unavailable”:表示服务器当前很忙,暂时无法响应客户端。我们上网时有时候遇到的 “网络服务正忙,请稍后重试” 的提示信息就是状态码503 - “
504 Gateway Timeout”:服务器作为网关或代理,但是没有及时从上游服务器收到请求
- “

详细链接:[12 响应状态码该怎么用?](https://learn.lianglianglee.com/专栏/透视HTTP协议/12 响应状态码该怎么用?.md)
什么情况下会出现502错误码呢?
答:
如果客户端访问服务器是通过 Nginx 来反向代理到应用服务器,那么如果应用服务器出现了故障,导致Nginx 无法从应用服务器获取到响应,这时候 Nginx 就会返回 502 错误码给客户端
补充:
502(Bad Gateway)状态代码表示服务器在充当网关或代理时,在尝试满足请求时从它访问的入站服务器接收到无效响应- 简单理解就是,
502其实是由 网关代理(Nginx)发出的,是因为 网关代理把客户端的请求转发给了服务端,但服务端却发出了无效响应,而这里的无效响应,一般是指TCP的RST报文或四次挥手的FIN报文- 屏蔽掉具体有哪些服务器的代理方式 就是所谓的 反向代理
- 异常情况下,收发双方都不一定正常,连四次挥手这件事本身都可能做不到,所以就需要一个机制去强行关闭连接:
RST一般用来异常地关闭一个连接,它是TCP包头中的一个标志位,在收到置这个标志位的数据包后,连接就会被关闭,此时接收到RST的一方,在应用层会看到一个connection reset或connection refused的报错


详细链接:502问题怎么排查?你学会了吗?-502问题怎么解决
有个服务出现了504,你觉得这个服务是出了什么问题?
答:
504是 网关超时错误,通常是 Nginx 将请求代理到后端应用时,后端应用没有在规定的时间返回数据,需要开发检查下应用那块有什么耗时的操作,比如:是否出现了 sql 慢查询,接口是否发生死循环、死锁 等问题,然后后端服务器系统负载高不高
重定向是哪一类状态码?临时重定向和永久重定向有什么区别?
答:
- 重定向 是数字
3开头的状态码- 客户端收到
301状态码后,会记忆重定向后的URL地址,这样下一次访301状态码是代表永久重定向,问的时候,不需要访问旧URL,直接跳转到新URL访问 302状态码代表 临时重定向,客户端收到302状态码后,不会记忆重定向后的URL地址,下一次访问的时候,还需要访问旧的URL,再跳转访问新的URL
- 客户端收到
补充:
301永久重定向,浏览器会记住- 假如:当你访问
a.com时,永久重定向到了b.com;那么下一次访问a.com时浏览器会直接跳转到b.com不会再请求a.com
- 假如:当你访问
302临时重定向,浏览器不会记忆- 假如:加入当你访问
a.com时 临时重定向到了b.com;那么下一次当你请求a.com时,浏览器还会先请求a.com,然后再重定向到b.com
- 假如:加入当你访问
详细链接:重定向的理解301,302 - 知乎
HTTP 是长连接还是短连接?
答:
HTTP 1.0 虽然支持长连接,但是 默认的连接行为是 短链接,从 HTTP1.1 版本之后,都是 默认长连接了
补充:
在 HTTP 1.0 中默认是关闭的,如果浏览器要开启 Keep-Alive,它必须在请求的包头中添加:
1 | Connection:Keep-Alive |
然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中:
1 | Connection: Keep-Alive |
这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端提出断开连接
从 HTTP 1.1 开始, 就默认是开启了 Keep-Alive,如果要关闭 Keep-Alive,需要在 HTTP 请求的包头里添
加:
1 | Connection:close |
现在大多数浏览器都默认是使用 HTTP/1.1,所以 Keep-Alive 都是默认打开的。一旦客户端和服务端达成协议,那么长连接就建立好了,HTTP 长连接的优势是可以减少了 TCP 连接资源的开销
详细链接:4.15 TCP Keepalive 和 HTTP Keep-Alive 是一个东西吗? | 小林coding
HTTP 长连接和短连接的区别?
答:
- 短连接:每次通信请求都需要建立新的连接,请求完成后立即关闭连接。这样每次请求都需要建立连接和释放连接,会增加通信开销和延迟
- 长连接:在通信过程中保持连接的持续性,多次请求可以共享同一个连接。在长连接中,客户端和服务器建立连接后可以进行多次请求和响应,减少了连接建立和释放的开销,提高了通信效率
补充:
短连接:每次通信请求都需要建立新的连接,请求完成后立即关闭连接,下次请求还需要重新建立 TCP 连
接

长连接:在通信过程中保持连接的持续性,多次请求可以共享同一个 TCP 连接

HTTP 长连接有什么好处?
答:
长连接 可以在一次 TCP 连接中可以发送和响应多个 HTTP 请求,可以减少了 TCP 连接资源创建和断开的开销
补充:
- 短连接:在一次
TCP连接中只能发送和响应一个HTTP请求,即:建立TCP→ 请求资源 → 响应资源 → 释放连接 - 长连接:在一次
TCP连接中可以发送和响应多个HTTP请求,即:建立TCP → 请求资源 → 响应资源 → 请求资源 → 响应资源 → 请求资源 → 响应资源 → 请求资源 → 响应资源 → … → 释放连接
HTTP/1.0 和 HTTP/1.1 的区别?
答:
- 长连接:
HTTP/1.1默认的连接行为是 长连接,而HTTP/1.0虽然也支持 长连接,但是默认是使用 短连接 - 请求管道化:
HTTP/1.1支持 请求管道传输(pipline)的方式,HTTP/1.0不支持这个模式,HTTP/1.0请求和响应必须是串行的,当一个请求和它响应完成之后,才能发送下一个请求,而HTTP/1.1由于支持管道传输方式,因此可以并发发送HTTP请求,能够提高HTTP请求的效率,但是HTTP响应还是得按顺序响应,只有HTTP/2.0实现了HTTP请求和响应的并发传输的能力 host字段:通过host头部字段,一个物理服务器可以承载多个域名或站点HTTP/1.0没有host字段,HTTP/1.1新增了host字段
补充:
HTTP/1.0 和 HTTP/1.1 两者的主要区别体现在:
-
长连接:在
HTTP/1.0中,默认使用的是短连接,也就是每次请求都要重新建立一次连接。HTTP是基于TCP/IP协议的,每一次建立或者断开连接,都需要三次握手四次挥手的开销,如果每次请求都要这样的话,开销会比较大,因此最好能维持一个长连接,可以用长连接来发多个请求。HTTP 1.1起,默认使用长连接connection:keep-alive -
请求管道化:
HTTP 1.1支持请求管道化,即:在一个持久连接上可以同时发送多个请求,而HTTP 1.0不支持请求管道化,HTTP/1.0请求和响应必须是串行的,当一个请求和它响应完成之后,才能发送下一个请求,而HTTP/1.1由于支持管道传输方式,因此可以并发发送HTTP请求,能够提高HTTP请求的效率
-
Host头字段:HTTP/1.0没有host字段,HTTP/1.1新增了host字段,通过Host头部字段,一个物理服务器可以承载多个域名或站点
-
错误响应码:在
HTTP 1.1中,新增了24个错误状态响应码- 例如:
409(Conflict):表示请求的资源与资源的当前状态发生冲突 410(Gone):表示服务器上的某个资源被永久性的删除
- 例如:
-
缓存处理:
HTTP 1.0中,主要使用header头里的If-Modified-since、Expires来做为缓存判断
的标准;HTTP 1.1,则引入了更多的缓存控制策略,如:Entity tag、If-Unmodified-since、If-Match、If-None-Match等 -
带宽优化及网络连接的使用:
HTTP 1.0中,存在一些浪费带宽的现象,例如:客户端只是需要某个对象的一部分,而服务器却将整个对象传送了过来,并且不支持断点续传功能;HTTP 1.1中,则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样方便开发者自由的选择,以便于充分利用带宽和连接
详细链接:阿里一面:HTTP 1.0 和 HTTP 1.1 有什么区别?-51CTO.COM
HTTP/1.1 和 HTTP/2.0 的区别?
答:
- 我认为
HTTP/1.1和HTTP/2.0最大的区别在于:HTTP/1.1无法实现请求和响应的并发传输,而HTTP/2.0能够实现请求和响应的并发传输- 原因:
HTTP/1.1虽然支持了管道化请求模式,能够并发传输HTTP请求,但是HTTP响应还是需要按顺序返回,无法做到HTTP响应并发传输。HTTP/2.0引入了stream的概念,不同的HTTP请求和响用不同的stream来区分,多个stream复用一条TCP连接,只需要一条连接就可以达到了并发传输的效果
- 原因:
HTTP2.0在HTTP报文格式上也做了改进,HTTP2.0用了HPACK算法压缩了HTTP头部,同时将HTTP/1.1纯文本的格式改进成了二进制格式,提高了数据传输的效率。HTTP2.0还支持服务器主动推送资源,比如:客户端在从服务器获取HTML文件时,可能这个页面渲染还需要其他CSS,这时候服务器可以接主动推送CSS文件,可以减少了消息传递的次数
补充:
HTTP/2.0 相比 HTTP/1.1 性能上的改进:
- 并发传输(最重要的区别)
- 头部压缩 + 二进制格式
- 服务器主动推送资源
详细链接:3.6 HTTP/2 牛逼在哪? | 小林coding
HTTP/2.0 和 HTTP/3.0 的区别?
答:
HTTP 2.0和3.0最大区别:传输层使用的协议不同。以往HTTP都是基于TCP协议进行传输,这次HTTP3.0改用UDP协议HTTP/2.0并发传输的特性,是在一条TCP连接上实现的这里会有TCP队头阻塞的问题,在传输过程中,假设:某个stream发生了丢包,服务端不仅不能处理这个stream,也不能处理其他stream,必须等这个包重传了,才能继续处理其他stream- 为了解决这个问题
HTTP/3.0将传输层改用UDP协议,并在UDP基础上实现了一个可靠传输的QUIC协议,当某个流发生丢包时,只会阻塞这个stream,其他stream不会受到影响,因此不存在队头阻塞问题
- 除此之外:
HTTP/3.0连接建立方面比HTTP/2.0更高效,HTTP/2.0建立连接的时候需要3次TCP握手 +TLS四次握手,而HTTP3.0的QUIC协议只需要3次握手就能完成连接建立(包括TLS握手建立)- 最后还有一点,
HTTP/3.0在网络环境切换的过程,可以不需要重新建立连接。以往HTTP都是基于TCP协议进行传输,TCP是根据 四元组信息 唯一确认一条连接,如果 四元组信息 某一个信息发生变化了,这时候就需要断开连接,重新建立连接,比如:4G网络切换到WIFI网络的时候,所有的TCP连接都需要重新建立,而HTTP/3.0是在应用层通过连接ID来唯一确认连接的,即使网络发生切换,也不会影响原本的连接,消除重连的成本
补充:
- 先提出
HTTP 2.0的缺陷,存在TCP队头阻塞问题,,然后再提HTTP/3.0是怎么解决的,最后再提HTTP3.0还有什么新特性
详细链接:3.7 HTTP/3 强势来袭 | 小林coding
HTTP 是无状态的吗?
答:
是的,HTTP 是无状态的,一般我们会通过 Cookie、Session、Token 这些机制来维护用户的状态
补充:
HTTP是 无状态 的,这意味着 每个请求都是独立的,服务器不会在多个请求之间保留关于客户端状态的信息,在每个HTTP请求中,服务器不会记住之前的请求或会话状态,因此每个请求都是相互独立的- 因此 服务器不知道请求两次之间是否是同一个用户。这会带来一个问题,用户登录后,切换到其他界面,进行操作,服务器端是无法判断是哪个用户登录的,每次进行页面跳转的时候,得重新登录
- 虽然
HTTP本身是无状态的,但可以通过一些机制来实现状态保持,其中最常见的方式是:使用Cookie、Session、Token来跟踪用户状态。通过在客户端存储会话信息或状态信息,服务器可以识别和跟踪特定用户的状态,以提供一定程度的状态保持功能
HTTP 用户后续的操作,服务端如何知道属于同一个用户?
如果服务端是一个集群机器?
答:
问题1:
- 可以使用
SessionCookie的机制 ,达到身份识别的效果 - 比如:我用 账号 和 密码 登录某电商,登录成功后,网站服务器会校验 用户 和 密码,如果没问题,网站服务器就会生成一个唯一
session id来标识我,然后将该session id设置到Cookie中发送给客户端,客户端再次访问网站时,会将该Cookie发送给服务器,服务器通过Cookie中的Session ID可以获取用户之前的状态信息,免去了重复登录的麻烦,实现了状态保持
补充:
HTTP 是 无状态 的,可以通过 Session Cookie 机制保持用户登陆的状态

- 用户 向 服务器 发送 用户名 和 密码
- 服务器验证通过后,在当前对话(
session)里面保存相关数据,比如:用户角色、登录时间等等 - 服务器向用户返回一个
session id,写入用户的Cookie(响应头字段Set-Cookie=session id) - 用户随后的每一次请求,都会通过
Cookie(请求头字段Cookie),将session id传回服务器 - 服务器收到
session id,找到前期保存的数据,由此得知用户的身份
问题2:
- 如果服务端是一个 集群机器 的话, 可以用一台
Redis来保存session数据,达到共享session的效果,不过这种方案存在 单点 的问题,如果Redis挂了,可能所有用户登陆状态都会消失了,虽然可以通过搭建Redis集群来保证避免 单点 问题,但是我觉得这个方案成本太高了 - 一种比较低的解决成本方案是,不用
session,而是改用JWT来实现用户凭证会比较好,因为JWT的状态信息是保存在客户端的,服务端不再保存状态信息,天然适合分布式系统
补充:
-
seesion这种方式扩展性不好,因为session状态信息是保存在服务器内存的,如果服务器是 集群,就要求session数据共享到每一台服务器,否则会出问题,比如:客户端登陆后,如果有一台服务器的内存没有session id的状态信息,当客户端请求到这台服务器后,服务器发现session id的状态信息不存在,就会让客户端重新进行用户登陆
-
解决方案:
-
第一种方案:将
session id集中保存在redis或者MySQL,服务器集群通过判断session id的状态信息在不在redis或者MySQL,来确定用户是否已经登陆 -
这种方案的缺陷是 单点故障 的问题(虽然也可以对
redis搭建集群,但是架构的成本太高了)
-
第二种方案:服务器索性不保存
session数据了,把状态信息保存在客户端,每次请求都发回服务器,这个就是token机制,为了保证token不被中间人篡改,可以 使用JWT的方式来进行身份识别,通常分布式系统都是采用JWT来进行身份状态识别
-
详细链接:凭证 | 凤凰架构
如果禁用 Cookie,怎么实现 Session?
答:
可以通过重写 URL 来实现 Session 机制,就是在 URL 中增加 session id 请求参数
补充:
-
禁用
Cookie代表无法使用响应头无法使用Set-Cookie字段,以及请求头无法使用Cookie字段,这时候就没办法通过HTTPCookie传输Session id了 -
这时候可以重写
URL,比如:1
2原始的URL: http://taobao.com/getitem?name=baymax&action=buy
重写后的uRL:http://taobao.com/getitem?sessionid=1wui87htentg&name=baymax&action=buy
cookie 和 session 的区别?
答:
- 存储位置:
Cookie存储在浏览器,Session存储在服务端 - 存储大小:
Cookie是存储在浏览器的,浏览器对单个Cookie存储大小有限制的,限制保存的数据不能超过4K,而Session是存储在服务端的,所以没有这个限制 - 安全性:
Cookie存储在客户端,比较容易遭到不法获取,会容易遭到XSS和CSRF的攻击,而Session存储在服务端,安全性相对Cookie要好一些 - 有效期:
Cookie可设置为长时间保持,比如:经常使用的默认登录功能,Session一般失效时间较短,客户端关闭或者Session超时都会失效
补充:
Cookie是 服务器 发送到 用户浏览器 并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上- 通常,它用于 告知服务器两个请求是否来自同一浏览器。如:保持用户的登录状态,
Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能
- 通常,它用于 告知服务器两个请求是否来自同一浏览器。如:保持用户的登录状态,
Session代表着 服务器 和 客户端 一次会话的过程。Session对象存储 特定用户会话 所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者Session超时失效时会话结束Cookie和Session都是Web开发中用于跟踪用户状态的技术,但它们在 存储位置、存储大小、安全性、生命周期 等方面存在显著差异:- 存储位置:
Cookie的数据存储在客户端(通常是浏览器)。当 浏览器 向 服务器 发送请求时,会自动附带Cookie中的数据Session的数据存储在服务器端。服务器为每个用户分配一个唯一的Session ID,这个ID通常通过Cookie或URL重写的方式发送给客户端,客户端后续的请求会带上这个Session ID,服务器根据ID查找对应的Session数据
- 存储大小:
- 单个
Cookie的大小限制通常在4KB左右,而且大多数浏览器对每个域名的总Cookie数量也有限制 - 由于
Session存储在服务器上,理论上不受数据大小的限制,主要受限于服务器的内存大小
- 单个
- 安全性:
Cookie相对不安全,因为数据存储在客户端,容易受到XSS(跨站脚本攻击)的威胁。不过,可以通过设置HttpOnly属性来防止JavaScript访问,减少XSS攻击的风险,但仍然可能受到CSRF(跨站请求伪造)的攻击Session通常认为比Cookie更安全,因为敏感数据存储在服务器端。但仍然需要防范Session劫持(通过获取他人的Session ID)和会话固定攻击。
- 生命周期:
Cookie可以设置过期时间,过期后自动删除。也可以设置为会话Cookie,即:浏览器关闭时自动删除Session在默认情况下,当用户关闭浏览器时,Session结束。但服务器也可以设置Session的超时时间,超过这个时间未活动,Session也会失效
Cookie、session 和 Token 有什么区别?
答:
- 存储位置不同:
Cookie存储在 客户端,即:浏览器中的文本文件,通过在HTTP头中传递给服务器来进行通信Session是 服务器端 的存储方式,通常存储在服务器的内存或数据库中Token也是存储在 客户端,但是通常以加密的方式存储在客户端的localStorage或sessionStorage中
- 数据安全性不同:
Cookie存储在 客户端,可能会被窃取或篡改,因此对敏感信息的存储需要进行加密处理Session存储在 服务器端,通过一个Session ID在客户端和服务器之间进行关联,可以避免敏感数据直接暴露Token通常使用 加密算法 生成,有效期较短且单向不可逆,可以提供较高的安全性
- 跨域支持不同:
- 为了防止安全事故,因此
Cookie是不支持跨域传输的,也就是不同域名下的Cookie是不能相互访问 Session机制通常是通过Cookie来保存Session ID的,因此Session ID默认情况下也是不支持跨域的- 但
Token可以轻松实现跨域,因为Token是存储在客户端的localStorage或者作为请求头的一部分发送到服务器的,所以不同的域名Token信息传输通常是不受影响的
- 为了防止安全事故,因此
- 状态管理不同:
Cookie是应用程序通过在客户端存储临时数据,用于实现状态管理的一种机制Session是服务器端记录用户状态的方式,服务器会为每个会话分配一个唯一的Session ID,并将其与用户状态相关联Token是一种用于认证和授权的一种机制,通常表示用户的身份信息和权限信息
补充:
Cookie、Session 和 Token 通常都是用来保存用户登录信息的技术,但三者有很大的区别,简单来说:Cookie 适用于 简单的状态 管理,Session 适用于 需要保护用户敏感信息的场景,而 Token 适用于 状态无关的身份验证和授权
简述 JWT 的原理和校验机制?
答:
JWT令牌是由 3 个部分组成,分别是:头部、负载、签名- 头部:描述令牌使用的签名算法,负载:描述的是用户信息,比如:用户名称、过期时间等等
- 头部 和 负载 都是 不会被加密 的,只是会用
base64编码 - 最后一部分是 签名,是对 头部 和 负载 两部分数据的签名,签名的过程是,使用 头部 的签名算法,通过 服务器的密钥 对 前面两部分 内容进行 加密 计算
- 校验
JWT令牌的过程:- 服务端 收到 客户端 发过来的
JWT令牌后,服务端 会取出 头部 和 负载 数据,然后用自己的 密钥 对 这两部分数据 进行 加密 计算,将得到的 加密结果 和 客户端 发过来JWT的签名进行对比 - 如果相同,就表示前面两部分没有被中间人篡改,这时候服务器就可以进行其他验证,比如:检查
JWT是否过期,如果也没问题,就会正常执行业务逻辑
- 服务端 收到 客户端 发过来的
补充:

- 左边的字符串呈现了
JWT令牌的本体,右边的JSON结构是JWT令牌中携带的信息

-
JWT格式是header.payload.signature -
JWT共由 3 个部分信息组成:-
Header(头部):描述了 令牌的类型(统一为type:JWT)以及 令牌签名的算法(默认HMACSHA256算法),header信息不做加密,只做一般的base64编码,目的是替换URL里面有特殊含义
-
Payload(负载):这是 令牌真正需要向服务端传递的信息。针对 认证 问题,负载至少应该包含能够告知服务端 “这个用户是谁” 的信息,JWT的负载部分是可以完全自定义的,根据具体要解决的问题不同,设计自己所需要的信息。Payload信息不做加密,只做一般的base64编码,目的是替换URL里面有特殊含义
-
Signature(签名):是对前两部分的签名,防止数据篡改。签名的意思是:使用在Header中公开的特定签名算法,通过特定的密钥(Secret,由服务器进行保密,不能公开)对前面两部分内容进行加密计算
-
-
验证
JWT令牌的流程:- 服务端 收到 客户端 发过来
JWT令牌之后,取出header + payload,然后 服务端 根据自己的加密密钥进行加密计算 - 然后把 加密 的结果和 客户端 发过来
JWT的signature进行对比,如果完全相同,则表示前面两部分没有动过,就是自己颁发的,如果不同,肯定是被篡改过了 - 当令牌验证为没有被篡改后,服务器可以进行其他验证,比如:是否过期、用户是否有权限访问 等等
- 服务端 收到 客户端 发过来
JWT 令牌为什么能解决集群部署?
答:
JWT 包含 身份验证 和 会话信息,可以让服务器无需存储会话信息,就让服务器成为无状态的了,从而比较容易实现扩展
补充:
JWT令牌通过在令牌中包含所有必要的 身份验证 和 会话信息,使得服务器无需存储会话信息,从而解决了集群部署中的身份验证和会话管理问题。当用户进行登录认证后,服务器将生成一个JWT令牌并返回给客户端。客户端在后续的请求中携带该令牌,服务器可以通过对令牌进行验证和解析来获取用户身份和权限信息,而无需访问共享的会话存储- 由于
JWT令牌是自包含的,服务器可以独立地对令牌进行验证,而不需要依赖其他服务器或共享存储 - 这使得集群中的每个服务器都可以独立处理请求,提高了系统的可伸缩性和容错性
JWT 有什么缺点?
答:
JWT的最大缺点是 令牌难以主动失效,一旦JWT签发了,在到期之前就会始终有效,除非服务器搞了额外的逻辑,比如:设计一个 “黑名单” 的额外的逻辑,用来把要主动失效的令牌集中存储起来,然后,每次使用JWT进行请求的话都会先判断这个JWT是否存在于黑名单中JWT要防止盗用的问题,因为JWT包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限,为了减少盗用,JWT的有效期应该设置得比较短,而且不应该使用HTTP协议明码传输,要使用HTTPS协议传输
补充:
JWT 的缺点:
- 令牌难以主动失效:
JWT令牌一旦签发,理论上就和认证服务器再没有什么瓜葛了,在到期之前就会始终有效,除非服务器部署额外的逻辑去处理失效问题,这对某些管理功能的实现是很不利的- 譬如一种颇为常见的需求是:要求一个用户只能在一台设备上登录,在 B 设备登录后,之前已经登录过的 A 设备就应该自动退出。如果采用
JWT,就必须设计一个 “黑名单” 的额外的逻辑,用来把要主动失效的令牌集中存储起来,而无论这个黑名单是实现在Session、Redis或者 数据库 中,都会让服务退化成有状态服务,降低了JWT本身的价值,但黑名单在使用JWT时依然是很常见的做法,需要维护的黑名单一般是很小的状态量,许多场景中还是有存在价值的
- 譬如一种颇为常见的需求是:要求一个用户只能在一台设备上登录,在 B 设备登录后,之前已经登录过的 A 设备就应该自动退出。如果采用
- 必须考虑令牌在客户端如何存储:严谨地说,这个并不是
JWT的问题而是系统设计的问题。如果授权之后,操作完关掉浏览器就结束了,那把令牌放到内存里面,压根不考虑持久化才是最理想的方案。但并不是谁都能忍受一个网站关闭之后下次就一定强制要重新登录的。这样的话,想想客户端该把令牌存放到哪里 是Cookie?、localStorage?、Indexed DB?它们都有泄漏的可能,而令牌一旦泄漏,别人就可以冒充用户的身份做任何事情。为了减少盗用,JWT的有效期应该设置得比较短,而且JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输
什么是跨域?什么情况下会发生跨域请求?
答:
- 当一个网页去尝试访问不同源的资源的时候,就意味着发生了 跨域请求,只要 域名、协议、端口 这三个信息任意一个不同,都认为是不同源的
URL - 跨域请求 在 浏览器 上是 不被允许的,只要在浏览器上发生跨域请求操作时,浏览器就会自动抛出的错误。如果想绕过这个限制,可以用 跨域资源共享(
CORS)技术- 实现的方式:服务器需要在 响应头 上添加
Access-Control-Allow-Origin的字段,这个字段是设置为需要放行的域名,浏览器识别到了,才能放行该请界
- 实现的方式:服务器需要在 响应头 上添加
补充:
- 在浏览器环境下,当一个网页的脚本尝试去访问不同源(域名、协议、端口)的资源时,就会发生跨域请求。同源策略 是 浏览器 的一种安全机制,它限制了一个网页中的脚本只能访问同源下的资源,而不能直接访问其他域下的资源
- 在以下情况下会发生跨域请求:
- 域名不同:当浏览器中的网页从一个域名(例如:
www.example.com)发起请求访问另一个域名(例如:api.example.com)的资源时,就会发生跨域请求 - 协议不同:当浏览器中的网页从一个协议(例如:
http://)发起请求访问另一个协议(例如:https://)的资源时,也会发生跨域请求 - 端口不同:当浏览器中的网页从一个端口(例如:http://example.com:8080)发起请求访问另一个端口(例如:http://example.com:3000)的资源时,同样会发生跨域请求。
- 域名不同:当浏览器中的网页从一个域名(例如:
- 跨域请求会受到 同源策略 的限制,可以通过下面这些方式绕过限制:
- 使用反向代理:通过
Nginx等工具设置反向代理,将跨域请求转发到目标服务器 JSONP:网页通过添加一个script元素,向服务器请求JSON数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。缺点是:只支持get请求,不支持post请求CORS:在服务端设置响应头部信息,允许特定源的请求访问
- 使用反向代理:通过
RestFul 是什么?RestFul 请求的 URL 有什么特点?
答:
RestFul是一种API接口设计规范,用URL定位资源,用HTTP方法表示接口的动作,用HTTP状态码表示接口处理的情况RestFul风格的HTTP接口可以通过URL就能判定这个接口是做什么的/articles POST:代表新增一个文章/articles GET:代表获取全部文章- 有可能后边带参数进行一些过滤查询或分页,
/articles/1 GET:代表获取id为1这篇文章 /articles/1 PUT:代表更新id为1的文章- 请求体可能会带一些更新内容,
/articles/1 DELETE:代表删除id为1的文章
补充:
RestFul 简单理解就是用 URL 定位资源,用 HTTP 动词(GET、POST、DELETE、PUT)描述操作
详细链接:RESTful API 设计指南 - 阮一峰的网络日志、(13 封私信 / 33 条消息) 怎样用通俗的语言解释REST,以及RESTful? - 知乎
HTTPS
HTTP 和 HTTPS 有什么区别?
答:
我的理解主要有 4 个方面的区别:
- 安全性:
HTTP是明文传输协议,数据在传输过程中不加密,容易被窃听和篡改。而HTTPS通过使用SSL/TLS协议对数据进行加密,提供了更高的安全性和数据保护 - 建立连接:
HTTP连接建立相对简单,TCP三次握手之后便可进行HTTP的报文传输。而HTTPS在TCP三次握手之后,还需进行SSL/TLS的握手过程,才可进入加密报文传输 - 端口号:
HTTP默认使用 端口号80进行通信,而HTTPS默认使用端口号443 - 证书:
HTTPS需要使用数字证书来验证服务器的身份,并确保数据传输的安全性。证书由受信任的第三方机构颁发,用于证明服务器的身份和所有权。而HTTP没有使用证书进行身份验证和加密
了解过哪些加密算法?
答:
- 我主要了解 对称加密算法、非对称加密算法、哈希算法 这三种加密算法:
- 在
HTTPS协议里,对称加密算法 和 非对称加密算法 这两种算法都会用到- 对称加密算法就是用一个密钥进行加解密,比如:
AES算法;非对称加密则是有 2 个密钥,分别是 公钥和 私钥,比如:RSA算法。对称加密算法 适用于 大量数据 的 加密 和 解密,而 非对称加密算法 适用于 密钥交换 和 数字签名 等场景
- 对称加密算法就是用一个密钥进行加解密,比如:
- 哈希算法 主要用过
MD5算法,哈希算法 是一种 单向算法,用户可以通过 哈希算法 对目标信息生成一段特定长度的唯一的哈希值,却不能通过这个哈希值重新获得目标信息,所以用于数据完整性校验方面
详细链接:常用的加密算法_51CTO博客_常用的加密算法有哪些
对称加密和非对称加密是什么?各自有哪些算法?
答:
- 对称加密 和 解密 都是用 同一个密钥 进行操作,加密 和 解密 过程速度较快,适合对大量数据进行加密,对称密钥必须保密,不能明文传输,常见的对称加密算法有
AES、DES等 - 非对称加密使用 两个密钥,分别是 公钥 和 私钥,加密 和 解密 过程相对较慢,适合对少量数据进行加密。公钥 可以 任意分发,而 私钥 必须 保密,可以通过 公钥加密对称密钥,私钥解密 的方式,保证对称密钥的安全传输,常见的非对称加密算法有
RSA、ECC等
补充:
-
密钥区别:
- 对称加密:使用同一个密钥进行加密和解密。这意味着加密方和解密方必须事先共享同一个密钥,并且保证这个密钥的安全
- 非对称加密:使用一对密钥,一个公开密钥(公钥)用于加密,一个私有密钥(私钥)用于解密。公钥可以公开分享,而私钥必须保持私密
-
加密速度区别:
- 对称加密:通常更快,因为它使用较简单的算法来处理大量数据
- 非对称加密:由于其复杂的数学运算,尤其是在处理大量数据时,比对称加密得多
-
使用场景区别:
- 对称加密:适用于需要快速处理大量数据的场景,如:文件加密、数据库加密、网络数据传输加密等
- 非对称加密:由于其速度较慢,通常用于加密少量数据或用于加密对称加密中使用的密钥
-
典型的加密算法:
-
对称加密算法:
AES(高级加密标准)、DES(数据加密标准)、3DES(三重数据加密算法)等
-
非对称加密算法:
RSA、ECC(椭圆曲线密码学)等
-
详细链接:浅谈常见的七种加密算法及实现数字签名、信息加密 是前后端开发都经常需要使用到的技术,应用场景包括了用户登入、交易、信息通 - 掘金
对称和非对称的加密算法的区别?
答:
- 我理解的区别:
- 对称 加密 和 解密 都是用 同一个密钥 进行操作,加密和解密过程速度较快,适合对大量数据进行加密,对称密钥必须保密,不能明文传输
- 非对称 加密使用 两个密钥,分别是 公钥 和 私钥,加密和解密过程相对较慢,适合对少量数据进行加密。公钥可以任意分发,而私钥必须保密,可以通过公钥加密对称密钥,私钥解密的方式,保证对称密钥的安全传输
HTTPS采用的就是这样的混合加密方式- 在 通信建立前 采用 非对称加密 的方式 交换「对称密钥」,后续就不再使用非对称加密。在 通信过程中 全部 使用「对称密钥」的方式加密明文数据
补充:
可以从 加解密速度 + 密钥传输安全性 两个方向来说明区别
假设有一个文件,大小未知,现在要把它上传到云端,该使用对称加密还是非对称加密算法?
答:
使用对称加密算法比较好,因为对称加密算法运算速度是比非对称加密更快的,比较适合数据量大常见的加密
补充:
- 对称密钥加密速度会比非对称密钥快,针对数据量比较大的场景,要选择对称密钥来加密。对称加密比非对称加密快的原因:
- 对称加密 主要的运算是 位运算,速度非常快,如果使用硬件计算,速度会更快,但是非对称加密计算一般都比较复杂,比如:
RSA,它里面涉及到 大数乘法、大数模 等等运算 - 除了慢,可能还有一个缺点就是需要更多的位数,相同强度的对称密钥要比非对称密钥短。对称密钥一般都 128 位、256 位,而
RSA一般要 2048 位,不过圆曲线的会短一点
- 对称加密 主要的运算是 位运算,速度非常快,如果使用硬件计算,速度会更快,但是非对称加密计算一般都比较复杂,比如:
详细链接:为什么非对称加密比对称加密慢?-腾讯云开发者社区-腾讯云
HTTPS 建立的过程是怎么样的?
答:
- 首先 客户端 要和 服务端 先进行
TCP三次握手建立TCP连接。接下来,会进行TLS四次握手:- 第一次
TLS握手:客户端首先会发一个Client Hello消息,消息里面有 客户端使用的TLS版本号、支持的密码套件列表、客户端生成的随机数,这个随机数是用来后面生成对称密钥元素之一 - 第二次
TLS握手:当服务端收到客户端的消息后,会返回Server Hello消息给的客户端,消息里面有服务器确认的TLS版本号、密码套件、服务端生成的随机数。接着服务端为了证明自己的身份,会发送Server Certificate给客户端,这个消息里含有数字证书。随后,服务端发了Server Hello Done消息,目的是告诉客户端,我已经把该给你的东西都给你了,本次握手完毕- 校验证书:客户端收到服务端的数字证书的时候,会对校验服务端的证书,如果证书是合法的,客户端会用
CA机构的公钥解密数字证书拿到服务端的公钥
- 校验证书:客户端收到服务端的数字证书的时候,会对校验服务端的证书,如果证书是合法的,客户端会用
- 第三次
TLS握手:客户端再次生成一个随机数,用服务端的公钥加密后,通过Client Key Exchange消息传给服务端。服务端收到后,用服务端的私钥解密得到客户端的第二个随机数。到这里,服务端和客户端双方都有 3 个随机数,双方根据已经得到的三个随机数,会根据算法生成对称密钥。生成完对称密钥后,客户端会发一个消息告诉服务端开始使用对称加密方式发送消息,并且还会对之前所有发送的数据做个摘要,再用对称加密加密一下,让服务器做个验证,验证对称密钥是否可用,以及之前握手信息是否有被中途篡改 - 第四次
TLS握手:服务器也是同样的操作,发送消息告诉客户端开始用对称加密方式发送消息,并且也会对数据做个摘要,并用对称密钥加密一下,让客户端做个校验,如果双方都验证加密和解密没问题,那么TLS四次握手正式完成了
- 第一次
- 最后,就用对称密钥加解密
HTTP请求和响应了
补充:

详细链接:3.3 HTTPS RSA 握手解析 | 小林coding
为什么需要三个随机数?
答:
因为计算机生成的随机数其实是一个伪随机,那么只用一个随机数来生成的对称密钥很容易就被破解了,用三个伪随机数就十分接近随机了,这样称密钥破解的难度都变高了
补充:
- 不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于
SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性 - 对于
RSA密钥交换算法来说,pre-master-key(第三个随机数)本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥 pre master(第三个随机数)的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret(第三个随机数)作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一
详细链接:SSL/TLS协议运行机制的概述 - 阮一峰的网络日志
一次HTTPS需要几次RTT(就是几个来回)?
答:
HTTPS 是四次握手,那么就是 2 次 RTT
补充:
RTT 是往返的延时,HTTPS 是四次握手,也就是代表 2 次往返,那么就是 2 次 RTT
详细链接:3.3 HTTPS RSA 握手解析 | 小林coding
你了解业界现在有一个RTT建立HTTPS连接的方案吗?
答:
基于 ECDHE 密钥交换的 HTTPS 连接方案,可以实现1 个 RTT 建立 HTTPS 连接
补充:
-
TLS1.2 版本如果使用的是RSA密钥交换算法,那么需要 4 次握手,也就是要花费 2RTT,才可以进行应用数据的传输 -
因此如果可以,尽量选用
ECDHE密钥交换算法(TLS1.3 版本使用)替换RSA算法,因为该算法由于支持「TLS False start」,客户端可以在TLS协议的第 3 次握手后,第 4 次握手之前,发送加密的应用数据,以此将TLS握手的消息往返由 2RTT减少到 1RTT
-
下图左边是基于
RSA算法的HTTPS建立流程,需要 2 个RTT,右边是基于ECDHE算法的HTTPS建立流程,只需要 1 个RTT
- 上图的右边部分就是
TLS1.3(基于ECDHE算法)的握手过程,可以发现TLS1.3 把Hello和 公钥 交换这两个消息合并成了一个消息,于是这样就减少到只需 1RTT就能完成TLS握手 - 具体的做法是:客户端在
Client Hello消息里带上了支持的椭圆曲线,以及这些椭圆曲线对应的公钥,服务端收到后,选定一个椭圆曲线等参数,然后返回消息时,带上服务端这边的公钥。经过这 1 个RTT,双方手上已经有生成会话密钥的材料了,于是客户端计算出会话密钥,就可以进行应用数据的加密传输了 - 服务端收到后,选定一个椭圆曲线等参数,然后返回消息时,带上服务端这边的公钥
- 经过这 1 个
RTT,双方手上已经有生成会话密钥的材料了,于是客户端计算出会话密钥,就可以进行应用数据的加密传输了
- 上图的右边部分就是
详细链接:3.5 HTTPS 如何优化? | 小林coding、3.4 HTTPS ECDHE 握手解析 | 小林coding
HTTPS 过程进行了多少次非对称加密?多少次对称加密?
答:
- 还未
HTTPS握手之前:- 服务端在向
CA机构注册证书的时候,CA机构会用CA私钥会对服务端的公钥进行签名,形成数字证书,这里涉及了 1 次非对称加密
- 服务端在向
HTTPS握手期间:- 客户端会用服务端的公钥加密随机数,服务端再用私钥解密,这里涉及了 1 次非对称加密
- 客户端和服务端生成对称密钥之后,都需要对之前握手的数据做个摘要,并用对称密钥加密一下,这个过程客户端和操作都会涉及到,所以
HTTPS握手期间用了 2 次对称加密,客户端和服务端各做了一次
HTTPS握手完成之后:HTTPS数据传输期间都是用对称密钥进行加密和解密
补充:
- 可以分
HTTPS握手之前、期间、之后三个时间段来回答
详细链接:3.3 HTTPS RSA 握手解析 | 小林coding
SSL 握手流程为什么要使用非对称加密?
答:
- 我的理解主要是为了保护对称加密钥不被中间人窃取,如果对称加密钥被窃取了,使用这个对称加密钥加密的
HTTP报文就很容易被破解了 - 在
HTTPS协议进行TLS握手的时候,客户端生成随机数,这个是生成对称加密钥元素之一,它会被公钥加密后传输给服务端,由服务端用私钥解密,这里就保证了对称加密钥的安全- 因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容
详细链接:3.3 HTTPS RSA 握手解析 | 小林coding
为什么 HTTPS 不用非对称加密算法加密 HTTP 报文?
答:
非对称加密算法的加密和解密操作相对比对称加密算法更消耗 CPU 计算力,也更耗时,而 HTTP 报文通常包含大量的数据,如果直接使用非对称加密算法对整个报文进行加密和解密,会导致性能下降和延迟增加
补充:
要重点说明非对称加密算法更消耗 CPU 计算力,不适合用来频繁的加解密
详细链接:为什么非对称加密比对称加密慢?这个问题是一个读者面试时遇到的一个问题,准备过面试的人应该都记得,非对称加密与对称加密的区 - 掘金
HTTPS 会对 URL 加密吗?
答:
URL 是属于 HTTP 报文头部的信息,HTTPS 会对整个 HTTP 报文都会加密,所以 HTTPS 是会对 URL 加密的
补充:
很多人看到浏览器的地址栏就以为 HTTPS 不会对 URL 进行加密,实际上 URL 是属于 HTTP 报文头部的信息,HTTPS 会对整个 HTTP 报文(header + body)都加密,所以 HTTPS 是会对 URL 加密,之所以浏览器能明文显示 URL,是因为浏览器已经帮我们解密好了
CA 机构如何验证server身份?
答:
服务端在向 CA 机构申请证书的时候,CA 机构会通过自己的私钥对服务器的一些信息进行数字签名,然后在 HTTPS 握手阶段的时候,服务端会发送证书给客户端来验证,客户端实际上已经内置了 CA 机构的公钥,那么就用这个公钥来验证服务端的数字证书是否是可信的
补充:


证书是绿色的是什么意思?
答:
代表网站是 可信的,浏览器在 HTTPS 握手阶段会对网站服务器下发的证书进行校验,,如果校验成功,代表网站的身份的可信的,是被 CA 机构认证过的
自己随便编一个证书可以吗?需要去什么地方注册?
答:
- 不可以
- 浏览器在校验这个证书的时候,会认为是非法的证书,这时候浏览器会显示访问的网站是不可信
- 得去
CA机构申请证书,浏览器才会认为是合法的证书,这样才能正常的访问网站的内容
补充:
- 数字证书的作用:是用来认证 公钥持有者 的身份,以防止第三方进行冒充
- 说简单些,证书就是用来告诉客户端,该服务端是否是合法的,因为只有证书合法,才代表服务端身份是可信的。我们用证书来认证公钥持有者的身份(服务端的身份)
- 那证书又是怎么来的?又该怎么认证证书呢?为了让服务端的公钥被大家信任,服务端的证书都是由
CA(Certificate Authority,证书认证机构)签名的,CA就是网络世界里的公安局、公证中心,具有极高的可信度,所以由它来给各个公钥签名,信任的一方签发的证书,那必然证书也是被信任的
详细链接:3.3 HTTPS RSA 握手解析 | 小林coding
RPC
RPC 的作用是什么?
答:
RPC是远程过程调用,主要运用于微服务之间的通信- 它的作用是帮助我们屏蔽网络编程细节,实现调用远程方法就跟调用本地(同一个项目中的方法)一样的体验,让我们更专注于业务逻辑,而无需关注底层网络通信的细节
补充:
RPC的全称是Remote Procedure Call,即:远程过程调用。简单解读字面上的意思,远程肯定是指要跨机器而非本机,所以需要用到网络编程才能实现,但是不是只要通过网络通信访问到另一台机器的应用程序,就可以称之为RPC调用了?显然并不够- 我理解的
RPC是帮助我们屏蔽网络编程细节,实现调用远程方法就跟调用本地(同一个项目中的方法)一样的体验,我们不需要因为这个方法是远程调用就需要编写很多与业务无关的代码。这就好比建在小河上的桥一样连接着河的两岸,如果没有小桥,我们需要通过划船、绕道等其他方式才能到达对面,但是有了小桥之后,我们就能像在路面上一样行走到达对面,并且跟在路面上行走的体验没有区别 - 所以我认为,
RPC的作用就是体现在这样两个方面:- 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法
- 隐藏底层网络通信的复杂性,让我们更专注于业务逻辑
为什么有HTTP协议了?还要用RPC?
答:
HTTP和RPC其实是两个维度的东西,HTTP指的是 通信协议。而RPC则是远程调用,其对应的是本地调用。RPC的通信可以用HTTP协议,也可以自定义协议,是不做约束的- 用
HTTP传输数据会有比较多的信息,比如:头部有各种字段信息,数据载体则一般是用json格式,而RPC因为它定制化程度更高,可以采用体积更小的protobuf或 其他序列化协议 去保存结构体数据,同时也不需要像HTTP那样考虑各种浏览器行为,比如:302重定向跳转啥的,因此性能也会更好一些,这也是在公司内部微服务中抛弃HTTP,选择使用RPC的最主要原因
补充:
RPC本质上不算是协议,而是一种调用方式,而像gRPC和Thrift这样的具体实现,才是协议,它们是实现了RPC调用的协议。目的是希望程序员能像调用本地方法那样去调用远端的服务方法。同时RPC有很多种实现方式,不一定非得基于TCP协议- 从发展历史来说,
HTTP主要用于B/S架构,而RPC更多用于C/S架构。但现在其实已经没分那么清了,B/S和C/S在慢慢融合。很多软件同时支持多端,所以对外一般用HTTP协议,而内部集群的微服务之间则采用RPC协议进行通讯 RPC其实比HTTP出现的要早,且比目前主流的HTTP/1.1性能要更好,所以大部分公司内部都还在使用RPCHTTP/2.0在HTTP/1.1的基础上做了优化,性能可能比很多RPC协议都要好,但由于是这几年才出来的- 所以也不太可能取代掉
RPC
详细链接:3.8 既然有 HTTP 协议,为什么还要有 RPC? | 小林coding
Nginx
Nginx 位于七层网络结构的哪一层?
答:
应用层,nginx 是七层负载均衡
补充:

- 常说的七层和四层负载均衡,是用
OSI网络模型来描述的,七层对应的是应用层,四层对应的是传输
层
详细链接:讲讲亿级PV的负载均衡架构-腾讯云开发者社区-腾讯云
Nginx 有哪些负载均衡算法?
答:
- 我了解到的主要有 普通轮询、加权轮询、
IP哈希、URL哈希、最短响应时间、最短连接 这些负载均衡算法 - 大体上可以分为下面几类:
- 任务平分类:负载均衡系统将收到的任务平均分配给服务器进行处理,这里的 “平均” 可以是绝对数量的平均,也可以是比例或者权重上的平均,比如:轮询 和 加权轮询算法
- 负载均衡类:负载均衡系统根据服务器的负载来进行分配,可以用
CPU负载来衡量,也可以用连接数I/O使用率、网卡吞吐量等来衡量系统的压力。比如:最短连接数算法 - 性能最优类:负载均衡系统根据服务器的响应时间来进行任务分配,优先将新任务分配给响应最快的服务器,比如:最短响应时间算法
Hash类:负载均衡系统根据任务中的某些关键信息进行Hash运算,将相同Hash值的请求分配到同一台服务器上,比如:IP哈希和URL算法
补充:
Nginx支持的负载均衡算法包括:- 轮询:按照顺序依次将请求分配给后端服务器。这种算法最简单,但是也无法处理某个节点变慢或者客户端操作有连续性的情况
- 加权轮询:按照权重分配请求给后端服务器,权重越高的服务器获得更多的请求。适用于后端服务器性能不同的场景,可以根据服务器权重分配请求,提高高性能服务器的利用率
IP哈希:根据客户端IP地址的哈希值来确定分配请求的后端服务器。适用于需要保持同一客户端的请求始终发送到同一台后端服务器的场景,如:会话保持URL哈希:按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率- 最短响应时间:按照后端服务器的响应时间来分配请求,响应时间短的优先分配。适用于后端服务器性能不均的场景,能够将请求发送到响应时间快的服务器,实现负载均衡
- 最短连接:新请求会发送到并发连接最少的服务节点
详细链接:面试官:你背一下负载均衡算法?
什么是反向代理?什么是正向代理?
答:
正向代理 代理的 客户端 这一方,而 反向代理 是代理 服务器 这一方,可以通过负载均衡策略,将请求分发到不同服务器上
补充:
- 正向代理 是位于用户设备和互联网之间的服务器。它代理的是客户端,是站在用户一方的。其真实客户端对于服务器不可见
- 正向代理通常用于:
- 保护客户端,隐藏客户端真实
IP,免受攻击 - 避免网络浏览限制(科学上网)
- 阻止访问某些内容
- 提高访问速度。通常代理服务器会有较大的硬盘缓冲区,将一些响应结果缓存在服务器端,以便后续用户取用
- 保护客户端,隐藏客户端真实
- 正向代理通常用于:
- 反向代理 是一种服务器,它接受客户端的请求,将请求转发给网络服务器,然后将结果返回给客户端,就像代理服务器处理了请求一样
- 反向代理代理的是服务器,是和网络服务器站在一方的。其真实服务器对于客户端不可见。这就是它叫 “反向” 的原因
- 反向代理可用于:
- 保护服务器,隐藏服务器真实
IP - 负载均衡,根据访问流量和服务器负载情况,将请求分发到不同服务器上
- 缓存静态内容以及部分短时间的大量动态请求
- 作为应用层防火墙提供防护,加密/解密
SSL通信
- 保护服务器,隐藏服务器真实
TCP 三次握手
TCP头部有哪些字段?
答:
- 我印象中
TCP头部字段主要有 出序列号、确认号、源端口号、目的端口号、标记位:SYN、ACK、FIN、RST、头部长度、窗口大小,可扩展的选项这些 - 其中,序列号和确认号都是 32 位大小,序列号可以保证数据的有序性,接收方会按照发送方顺序发送的数据来组装有序的数据,确认号可以保证数据的可靠性,当发送方已发送的数据,超过一段时间没收到确认报文,就会重传报文。然后,源端口号和目的端口号是 16 位大小,源端口是发送方使用的端口号,目的端口是接收方使用的端口号,端口的作用是标识
TCP连接是哪个进程的
补充:

- 源端口:16 位,标识报文的返回地址
- 目的端口:16 位,指明接收方计算机上的应用程序接口
- 序列号:32 位,在建立连接时由计算机生成的随机数作为其初始值,通过
SYN包传给接收端主机,每发送一次数据,就累加一次该数据字节数的大小。用来解决网络包乱序问题 - 确认号:32 位,指下一次期望收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题
- 数据偏移/首部长度:4 位,
TCP首部可能含有可选项内容,所以TCP报头的长度是不确定的,报头不包含任何任选字段则长度为 20 字节,4位首部长度字段所能表示最大长度为 60 字节。首部长度也叫数据偏移,因为首部长度实际上指示了数据区在报文段中的起始偏移值 - 保留:6 位,为将来定义新的用途保留,现在一般置 0
- 校验和:16 位,由发送端填充,接收端对
TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏,这个校验不仅包括TCP头部,也包括数据部分。这是TCP实现可靠传输的一个重要保障 - 窗口:16 位,是
TCP流量控制的一个手段。通过窗口告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方可以控制发送数据的速度,从而达到流量控制。窗口大小为 16 bit字段,因而窗口大小最大为 65535 - 紧急指针:16 位,只有当
URG标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。使用紧急指针是发送端向另一端发送紧急数据的一种方式 - 选项和填充:
TCP头部的最后一个选项字段是可变长的可选信息。这部分最多包含40字节,因为TCP头部最长是 60 字节- 最常见的可选字段是最长报文大小
MSS,每个连接方通常都在通信的第一个报文段中指明这个选项,它表示本端所能接受的最大报文段的长度
- 最常见的可选字段是最长报文大小
- 数据部分:
TCP报文段中的数据部分是可选的。在连接建立或者终止时,双方交换的报文段仅有TCP首部;如果一方没有数据要发送,也会使用没有任何数据的首部来确认收到的数据;在处理超时的许多情况中,也会发送不带任何数据的报文段
还包括控制位:
URG:紧急指针标志,为 1 时表示紧急指针有效,该报文应该优先传送,为 0 则忽略紧急指针ACK:确认序号标志,为 1 时表示确认号有效,为 0 表示报文中不含确认信息。携带ACK标识的TCP报文段被称为确认报文段RST:重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接,或者用于拒绝非法的报文段和拒绝连接请求。称携带RST标志的TCP报文段为复位报文段SYN:表示请求建立一个连接。称携带SYN标志的TCP报文段为同步报文段FIN:finish 标志,用于释放连接,为 1 时表示发送方已经没有数据发送了,即关闭本方数据流。称携带FIN标志的TCP报文段为结束报文段PSH:push 标志,为 1 表示是带有push标志的数据,指示接收方在接收到该报文段以后,应优先将这个报文段交给应用程序,而不是在缓冲区排队
详细链接:TCP之报文首部格式 - Jummyer - 博客园
说一下TCP三次握手的过程?
答:
TCP 三次握手的过程:
- 最开始双方的
TCP连接都处于close状态,服务端首先会监听一个端口,处于Listen状态 - 在第一次握手的时候,客户端会随机生成初始化序号,放到
TCP报文头部的序号字段中,同时把SYN标志设置为 1,这样就表示SYN报文。接着把这个SYN报文发送给服务端,之后客户端处于SYN_SENT状态 - 服务端收到
SYN报文后,首先服务端也会随机生成初始化序号,放到TCP报文头部的序号字段中,然后对 客户端的初始化序号+1 作为确认号,放到TCP报文头部的确认应答字段中,并将SYN和ACK标志设置为 1,这样就表示SYN-ACK报文,后把该报文发给客户端,之后服务端处于SYN_RCVD状态 - 客户端收到服务端
SYN-ACK报文后,客户端会回一个ACK确认报文,该报文的确认号是 服务端的初始化序号+1,并且ACK标志会设置为 1。之后客户端处于ESTABLISHED状态 - 服务端收到
ACK确认报文后,服务端也进入处于ESTABLISHED状态

为什么需要三次握手?两次不行吗?
答:
我的理解主要有两个原因:
- 第一个原因是:三次握手可以有效防止历史连接的建立,避免资源浪费。假设:网络中残留一个序号为 90 的
SYN报文,现在客户端向服务端发起了建立连接的请求,发送了一个序号为 100 的SYN报文,如果这时候服务端先收到的是序号为 90 的SYN报文,就代表收到了历史连接,这时候服务端会回复确认号为 90+1 的SYN-ACK报文,客户端收到后,发现其实自己期望收到的确认号是 100+1,而不是 90+1,所以会断开连接,并且回RST给服务端,服务端收到RST也就会断开连接了,这样就避免了历史连接的建立。如果是两次握手的话,服务端在收到第一次握手就会建立连接,如果这时候建立的历史连接,那么就会造成资源浪费了 - 第二个原因是:三次握手可以确认客户端和服务端是否同时具备发送和接收的能力。第一握手代表客户端具有发送能力,当服务端收到第一次握手并且响应了第二次握手,实际上这里就证明了服务端具有发送和接收,客户端收到了第二次握手,然后响应了第三次握手,才代表客户端有接收的能力。如果是两次握手的话,只能证明服务端具有发送和接收能力,以及客户端的发送能力,但是无法证明客户端具有接收的能力。
以上就是我觉得 TCP 需要三次握手的原因
如果第一次握手丢包,会发生什么?
答:
如果第一次握手丢包了,达到超时重传的时机的话,会进行重传 SYN 报文,如果重传次数达到最大次数,还是没有收到第二次握手的话,客户端就会断开链接了
补充:
-
当客户端想和服务端建立
TCP连接的时候,首先第一个发的就是SYN报文,然后进入到SYN_SENT状态 -
在这之后,如果客户端迟迟收不到服务端的
SYN-ACK报文(第二次握手),就会触发「超时重传」机制,重传SYN报文,而且重传的SYN报文的序列号都是一样的 -
不同版本的操作系统可能超时时间不同,有的 1 秒的,也有 3 秒的,这个超时时间是写死在内核里的,如果想要更改则需要重新编译内核,比较麻烦
-
当客户端在 1 秒后没收到服务端的
SYN-ACK报文后,客户端就会重发SYN报文,那到底重发几次呢?在Linux里,客户端的SYN报文最大重传次数由tcp_syn_retries内核参数控制,这个参数是可以自定义的,默认值一般是 5 -
通常,第一次超时重传是在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2 倍。当第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应
ACK,客户端就不再发送SYN包,然后断开TCP连接。所以,总耗时是 1+2+4+8+16+32=63 秒,大约 1 分钟左右 -
举个例子,假设
tcp_syn_retries参数值为 3,那么当客户端的SYN报文一直在网络中丢失时,会发生下图的过程:
-
具体过程:
- 当客户端超时重传 3 次
SYN报文后,由于tcp_syn_retries为 3,已达到最大重传次数,于是再等待段时间(时间为上一次超时时间的 2 倍),如果还是没能收到服务端的第二次握手(SYN-ACK报文)那么客户端就会断开连接
- 当客户端超时重传 3 次
如果第二次握手丢包,会发生什么?
答:
我的理解第二次握手 SYN-ACK 报文其实有两个目的
- 第一个是报文中的
ACK,是对第一次握手的确认报文,那么当第二次握手的丢失的时候,就会导致客户端长时间没有收到ACK而触发超时重传SYN报文(第一次握手) - 第二个是报文中的
SYN,是服务端发起建立TCP连接的报文,那么当第二次握手的丢失的时候,服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传SYN-ACK报文
补充:
- 第二次握手的
SYN-ACK报文其实有两个目的:- 第二次握手里的
ACK, 是对第一次握手的确认报文 - 第二次握手里的
SYN,是服务端发起建立TCP连接的报文
- 第二次握手里的
- 因为第二次握手报文里是包含对客户端的第一次握手的
ACK确认报文,所以,如果客户端迟迟没有收到第一次握手,那么客户端就觉得可能自己的SYN报文(第一次握手)丢失了,于是客户端就会触发超时重传机制,重传SYN报文 - 然后,因为第二次握手中包含服务端的
SYN报文,所以当客户端收到后,需要给服务端发送ACK确认报文(第三次握手),服务端才会认为该SYN报文被客户端收到了。那么,如果第二次握手丢失了,服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传SYN-ACK报文。

如果第三次握手丢包,会发生什么?
答:
我的理解是第三次握手的 ACK 是对第二次握手的 SYN 报文的确认,所以当第三次握手丢失了,如果服务端那一方迟迟收不到这个确认报文,就会触发超时重传机制,重传 SYN-ACK 报文,直到收到第三次握手,或者达到最大重传次数
补充:

TCP的半连接队列和全连接队列了解过吗?
答:
- 半连接队列:服务端收到客户端发起的
SYN请求后,内核会把未完成握手的连接存储到半连接队列,等待完成三次握手后转移到全连接队列 - 全连接队列:服务端收到第三次握手的
ACK后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到全连接队列,等待进程调用accept函数时把连接取出来
补充:
在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
- 半连接队列,也称
SYN队列 - 全连接队列,也称
accept队列
服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列,等待进程调用 accept 函数时把连接取出来

TCP 四次挥手
TCP 四次挥手的过程?
答:
- 客户端打算关闭连接,此时会发送一个
FIN报文,之后客户端进入FIN_WAIT_1状态 - 服务端收到
FIN报文后,就向客户端发送ACK应答报文,接着服务端进入CLOSE_WAIT状态 - 客户端收到服务端的
ACK应答报文后,之后进入FIN_WAIT_2状态 - 等待服务端处理完数据后,也向客户端发送
FIN报文,之后服务端进入LAST_ACK状态 - 客户端收到服务端的
FIN报文后,回一个ACK应答报文,之后进入TIME_WAIT状态 - 服务端收到了
ACK应答报文后,就进入了CLOSE状态,至此服务端已经完成连接的关闭 - 客户端在
TIME_WAIT状态经过 2MSL,一段时间后,自动进入CLOSE状态,至此客户端也完成连接的关闭
以上就是四次挥手的过程,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手

为什么 TCP 需要四次挥手?三次挥手不行吗?
答:
- 我的理解是
TCP是全双工协议,双方都具备发送和接收的能力,那么在断开连接的期间,要确保双方能发送完自己的数据 - 当客户端发送第一次挥手后,也就是
FIN报文的时候,其实就代表客户端告诉服务端 “我不会再发送数据了”,服务端收到后,服务器收到客户端的FIN报文时,内核会马上回一个ACK应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送FIN报文,而是将发送FIN报文的控制权交给服务端应用程序,如果服务端应用程序有数据要发送的话,就发完数据后,才调用关闭连接的函数。所以第二次挥手和第三次挥手通常不会合并一起发送,而是分开发送,所以就需要四次挥手 - 如果只有三次挥手,那么就可能出现一方还有数据没有发送完就被迫关闭连接的情况,这会导致数据的丢失
补充:
要重点表述四次握手的原因是,TCP 是全双工的协议,需要双方确认自己不再发送数据的时候,才会主动发送 FIN 报文
TIME_WAIT 是如何产生的?
答:
当 TCP 连接的主动关闭方关闭连接,与被动关闭方进行了四次挥手的时候,在主动关闭方发送完第四次挥手后,也就是最后一个 ACK 报文后,主动关闭方的 TCP 连接就会进入到 TIME_WAIT 状态,这个状态会持续 2MSL 的时长,以确保对方已经收到了最后一个 ACK 报文
补充:
TIME_WAIT 状态是发生在客户端,其实不是的,准确来说 TIME_WAIT 状态发生在主动关闭连接的一方,客户端和服务端都可以作为主动关闭连接的一方
为什么 TIME_WAIT 状态要等待 2MSL?
答:
我的理解主要有两个原因:
- 第一个原因:主要是为了避免本次连接的历史报文,被新的连接接收到这些历史报文,从而导致出错 ,
MSL表示TCP报文在网络中最大的存活时长,等待 2MSL 就可以让两个方向的报文可以在网络中自然消失这样新的连接就不会接收到历史报文了 - 第二个原因,是为了确保第四次挥手
ACK报文能被接收,从而帮助被动关闭方正常关闭连接。如果主动关闭方的第四次挥手的ACK报文丢失了,由于被动关闭方没有收到这个ACK报文,它会超时重传FIN包,主动关闭方TIME_WAIT状态等待期间会重新发送ACK报文,如果没有TIME_WAIT状态,那么就没办法重新发生ACK报文,也就没办法帮助被动关闭方正常关闭连接了
以上就是我对 TIME_WAIT 状态的理解
补充:
MSL是Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为TCP报文基于是IP协议的,而IP头中有一个TTL字段,是IP数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送ICMP报文通知源主机MSL与TTL的区别:MSL的单位是时间,而TTL是经过路由跳数。所以MSL应该要大于等于TTL消耗为 0 的时间,以确保报文已被自然消亡TTL的值一般是 64,Linux将MSL设置为 30 秒,意味着Linux认为数据报文经过 64 个路由器的时间不会超过 30 秒,如果超过了,就认为报文已经消失在网络中了TIME_WAIT等待 2 倍的MSL,比较合理的解释是:网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。比如:如果被动关闭方没有收到断开连接的最后的ACK报文,就会触发超时重发FIN报文,另一方接收到FIN后,会重发ACK给被动关闭方,一来一去正好 2 个MSL- 可以看到 2MSL时长,这其实是相当于至少允许报文丢失一次。比如:若
ACK在一个MSL内丢失,这样被动方重发的FIN会在第 2 个MSL内到达,TIME_WAIT状态的连接可以应对 - 为什么不是 4 或者 8MSL 的时长呢?你可以想象一个丢包率达到百分之一的糟糕网络,连续两次丢包的概率只有万分之一,这个概率实在是太小了,忽略它比解决它更具性价比
- 2MSL 的时间是从客户端接收到
FIN后发送ACK开始计时的。如果在TIME_WAIT时间内,因为客户端的ACK没有传输到服务端,客户端又接收到了服务端重发的FIN报文,那么 2MSL 时间将重新计时。在Linux系统里 2MSL 默认是 68 秒,那么一个 MSL 也就是 38 秒。Linux系统停留在TIME_WAIT的时间为固定的 60 秒
TIME_WAIT 过多有什么危害?
答:
- 客户端和服务端
TIME_WAIT过多,造成的影响是不同的- 如果客户端(主动发起关闭连接方)的
TIME_WAIT状态过多,占满了所有端口资源,那么就无法对「目的IP+ 目的PORT」都一样的服务端发起连接了,但是被使用的端口,还是可以继续对另外一个服务端发起连接的 - 因此,客户端(发起连接方)都是和「目的
IP+ 目的PORT」都一样的服务端建立连接的话,当客户端的TIME_WAIT状态连接过多的话,就会受端口资源限制,如果占满了所有端口资源,那么就无法再跟「目的IP+ 目的PORT」都一样的服务端建立连接了 - 不过,即使是在这种场景下,只要连接的是不同的服务端,端口是可以重复使用的,所以客户端还是可以向其他服务端发起连接的,这是因为内核在定位一个连接的时候,是通过四元组
(源IP、源端口、目的IP、目的端口)信息来定位的,并不会因为客户端的端口一样,而导致连接冲突。
- 如果客户端(主动发起关闭连接方)的
- 如果服务端(主动发起关闭连接方)的
TIME_WAIT状态过多,并不会导致端口资源受限,因为服务端只监听一个端口,而且由于一个四元组唯一确定一个TCP连接,因此理论上服务端可以建立很多连接,但是 TCP连接过多,会占用系统资源,比如:文件描述符、内存资源、CPU 资源、线程资源等
补充:
过多的 TIME_WAIT 状态主要的危害有两种:
- 第一是占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等
- 第二是占用端口资源,端口资源也是有限的,一般可以开启的端口为 32768~61000 也可以通过
net.ipv4.ip .local_port_range参数指定范围
客户端和服务端 TIME_WAIT 过多,造成的影响是不同的。所以要从客户端过多 TIME_WAIT 状态和服务端过多 TIME_WAIT 状态来回答
怎么解决 TIME_WAIT 状态过多的问题?
答:
- 如果是客户端有大量
time_wait状态,可以考虑开启tcp_tw_reuse参数,当发起新连接的时候,会复用处于time_wait状态的连接 - 如果是服务端的话,尽量让主动断开连接的方式,由客户端来进行,可以在应用层设计一个逻辑,当服务端要断开连接的时候,发送一个消息给客户端,客户端收到之后,由客户端来断开
tcp连接,这样服务端就不会有time_wait状态了。
补充:
可以分客户端和服务端来回答
- 客户端:开启
tcp_tw_reuse参数,客户端在调用connect()函数时,内核会随机找一个time_wait状态超过 1 秒的连接给新的连接复用 - 服务端:服务端不主动断开
tcp连接,将断开tcp连接的主动权交给客户端
服务端产生大量 TIME_WAIT 状态的原因是什么?
答:
主动关闭方才会有 TIME_WAIT 状态,当服务端有大量 TIME_WAIT 状态的连接的时候,代表服务端主动关闭了连接,我觉得可能的原因是:
HTTP没有使用长连接,这时候客户端和服务端都是短连接,服务端发送完HTTP响应后,就会主动关闭了连接,如果有大量的短连接过来,那么服务端就会出现大量的TIME_WAIT状态,如果是这个问题的话,解决方式就是让客户端和服务端都开启 HTTPKeep-Alive机制HTTP长连接的请求数量设置过小,Web服务端通常会有个参数,来定义一条HTTP长连接上最大能处理的请求数量,当超过最大限制时,就会主动关闭连接。比如:Nginx的keepalive_requests这个参数,默认是 100,味着每个HTTP长连接最多只能跑 100 次请求,因为当QPS请求很高的时候,Nginx就会频繁的关闭连接,那么此时服务端上就会出大量的TIME_WAIT状态。解决的方式也很简单,调大Nginx的keepalive_requests参数就行
补充:
主动关闭方才会有 TIME_WAIT 状态,所以就要分析服务端为什么会主动关闭连接?
- 第一个场景:
HTTP没有使用长连接 - 第二个场景:
HTTP长连接的请求数量达到上限
服务端产生大量 CLOSE_WAIT 状态的原因是什么?
答:
- 我觉得问题原因在于,是服务端没有及时调用
close关闭连接的函数,导致出现大量CLOSE_WAIT状态的连接,因为只有正确调用了close关闭连接函数的时候,TCP连接状态才会有从CLOSE_WAIT状态变为LAST_ACK状态 - 我觉得大概率服务端的代码的问题,这时候我们需要针对具体的代码一步一步的进行排查和定位,主要分析的方向就是服务端为什么没有调用
close
补充:
CLOSE_WAIT状态是「被动关闭方」才会有的状态,而且如果「被动关闭方」没有调用close函数关闭连接,那么就无法发出FIN报文,从而无法使得CLOSE_WAIT状态的连接转变为LAST_ACK状态- 所以,当服务端出现大量
CLOSE_WAIT状态的连接的时候,说明服务端的程序没有调用close函数关闭连接
如果server发送FIN之后,因为client挂掉了,收不到回应,会发生什么?
答:
会触发超时重传机制,重传 FIN 报文,如果 FIN 报文达到最大的重传次数之后,还是没有收到响应,那么server 就会断开链接了
补充:
只要发送的数据没有收到响应,都会触发超时重传,重传达到最大次数之后,就会关闭连接了
如果客户端宕机重启,收到了server 的 FIN,会发生什么?
答:
既然客户端宕机重启了,之前的 TCP 连接信息就不存在了,那么如果收到 server 的 FIN,会回 RST 报文给server,server 收到 RST 报文就会断开连接
补充:
如果 TCP 连接信息没有了,那么再次收到该 TCP 连接的报文,就会回 RST 报文
TCP 与 UDP
TCP 和 UDP 有什么区别?
答:
我觉得主要有这几个方面的区别:
TCP是面向连接的协议,在发送数据的时候,需要先建立TCP三次握手,而UDP无连接的协议,直接就可以发送数据TCP会通过超时重传、流量控制、拥塞控制保证数据的可靠传输,而UDP并没有这些特性,UDP不考虑数据的可靠性TCP发送的数据是以字节流的形式,没有边界。而UDP是一个包一个包的发送,是有边界的
所以,综合来看:
TCP的优势在于可以保证数据的可靠性,但是缺陷就是实时性没有UDP协议好UDP的优势在于足够简单,不用建立连接,数据直接丢过去即可,并且UDP包头比TCP包头小很多
所以 UDP 实时性和速度方面是比 TCP 好的
补充:
- 可以从几个角度分析:连接、可靠性、传输方式
- 最后总结,这两个协议的优劣势
详细链接:TCP vs UDP——哪个协议更快?
什么时候用 TCP?什么时候用 UDP?
答:
- 如果主要关注数据接收的可靠性和顺序,可以选使用
TCP,比如:FTP协议、HTTP协议都是基于TCP协议进行传输数据 - 如果主要关注的是速度和实时性,而且并不在意某些数据包的丢失,可以选使用
UDP协议,比如:直播视频会议场景
补充:
UDP 和 TCP 应用场景:
TCP传输速度慢,但是数据传输可靠性高UDP传输速度快,但是不保证传输的可靠性

此时此刻的视频面试用的 UDP 还是 TCP?UDP丢包会有什么现象?
答:
我觉得是 UDP 协议,因为视频会议这个场景下,重要的是实时性,UDP 协议实时性比 TCP 好,采用 UDP 协议传输音视频数据的话,如果发生了丢包,只是就丢失某一瞬间的画面和语音,然后还可以继续进行会议沟通,不会太影响视频会议的体验,如果是采用 TCP 协议的,由于 TCP 是可靠传输,如果发生了丢包,可能画面就卡住不动,等丢包重传才会推进画面,这样实时性就比较差了
详细链接:[34 UDP 协议:UDP 和 TCP 相比快在哪里?](https://learn.lianglianglee.com/专栏/重学操作系统-完/34 UDP 协议:UDP 和 TCP 相比快在哪里?.md)
UDP 怎么改造变为可靠传输?
答:
- 我会在应用层增加序列号字段,用来确保
UDP的数据可以按序接收,同时还会增加确认号,用来实现超时重传机制,当超过一定时间内没收到已发送数据的确认号,就重传该数据包 - 我还会在应用层开辟一个缓冲区,用来实现滑动窗口,有了滑动窗口这样发送数据可以先批量发送数据,不需要等上一个数据的确认了才能发送,提高了发送速率,同时还可以基于滑动窗口实现流量控制,用来保证发送方能按接收方的接收能力发送数据,避免发送的数据对方接收不了而发生数据丢失
- 最后,为了保证整个网络的带宽环境,还需要实现拥塞控制,确保发送方的数据,不会占满整个带宽
- 我觉得 UDP 实现可靠传输相比 TCP 可靠传输有几点优势:
- 拥塞控制算法可以根据不同的应用选用不同的拥塞控制算法,而
TCP选用拥塞控制算法的时候,是所有应用都使用这一套拥塞控制算法 - 升级方便,
TCP是在内核实现的,升级TCP需要升级操作系统,而UDP可靠传输是在应用层实现的,升级协议就像升级软件一样简单 - 可以实现网络连接迁移,在应用层用连接
id来唯一标识一个连接,不必像TCP那样,是通过四元组才确定连接的,只要四元组的信息发生了变化,就需要重新建立连接
- 拥塞控制算法可以根据不同的应用选用不同的拥塞控制算法,而
补充:
按照 TCP 协议怎么实现可靠传输的方式,在应用层实现一遍就好了,最后可以补充说明基于 UDP 协议实现的可靠传输相比于 TCP 有什么优势
TCP 和 UDP 可以共用一个端口吗?
答:
- 可以的
socket是根据五元组信息唯一确认的:协议类型、源 ip 地址、源端口、目标 ip 地址、目标端口,只要有一个信息不同,就会认为是不同的socket,不会引起冲突,所以TCP和UDP是可以共用一个端口号的
补充:
-
在数据链路层中,通过
MAC地址来寻找局域网中的主机。在网际层中,通过IP地址来寻找网络中互连的主机或路由器。在传输层中,需要通过端口进行寻址,来识别同一计算机中同时通信的不同应用程序 -
所以,传输层的「端口号」的作用,是为了区分同一个主机上不同应用程序的数据包
-
传输层有两个传输协议分别是
TCP和UDP,在内核中是两个完全独立的软件模块。当主机收到数据包后,可以在IP包头的「协议号」字段知道该数据包是TCP/UDP,所以可以根据这个信息确定送给哪个模块(TCP/UDP)处理,送给TCP/UDP模块的报文根据「端口号」确定送给哪个应用程序处理
-
因此,
TCP/UDP各自的端口号也相互独立,如:TCP有一个 80 号端口,UDP也可以有一个 80 号端口,二者并不冲突
详细链接:4.18 TCP 和 UDP 可以使用同一个端口吗? | 小林coding
TCP 可靠性
TCP 是如何保证可靠性的?
答:
- 连接建立:
TCP建立连接的时候,需要三次握手,这个过程可以证明双方都具有发送和接收的能力,并且能避免历史连接的建立 - 序列号与确认应答:
TCP头部有序列字段,可以保证数据的有序性,还有确认号,用来确认收到了数据 - 数据包重传:如果发送方发送的数据,长时间没有收到确认报文,就会触发超时重传,重传丢失的报文
- 滑动窗口机制:
TCP有流量控制的机制,发送方会根据接收方的接收窗口来发送数据报文,可以避免发送方发送的数据报文太大,导致接收方接收不了而丢包的问题 - 拥塞控制:
TCP有拥塞控制的机制, 通过慢启动、拥塞避免、拥塞发生,快速重传和快速恢复等算法调整发送速率来避免网络拥塞。当网络出现拥塞时,TCP会降低发送速率,以减少网络负载,保证数据的可靠传输
补充:
从 连接建立、序列号与确认应答、数据包重传、滑动窗口机制、拥塞控制 方面回答
详细链接:4.2 TCP 重传、滑动窗口、流量控制、拥塞控制 | 小林coding
TCP 流量控制和拥塞控制的区别?
答:
这两个机制都是 TCP 协议实现可靠传输的因素,主要区别在于:
- 流量控制:这是一个端到端的控制机制,目的是防止发送方发送的数据过快,导致接收方处理不过来。这通过滑动窗口机制实现,接收方在
ACK报文中告诉发送方自己的接收窗口大小,这样就告诉了发送方可以接收的最大数据量 - 拥塞控制:这是一个网络层面的控制机制,目的是防止过多的数据包同时在网络中传输,导致网络拥塞,主要是通过慢启动、拥塞避免、拥塞发生,快速重传和快速恢复,这几种算法实现的
所以,流量控制关注的是保护接收方不被淹没,而拥塞控制关注的是保护网络不被过载
滑动窗口怎么设计的?解决什么问题?
答:
发送方和接收方在内核各自都有一个缓冲区,发送缓冲区和接收缓冲区上都各有一个窗口,发送方的窗口表示可发送的最大数据量,接收方的窗口表示可接收的最大数据量:
- 发送方有了发送窗口后,那么发送方可以不用等待已发送数据的确认报文,就可以继续发送下一批数据,提高了发送的速率
- 接收方有了接收窗口后,可以实现流量控制,把接收方的接收窗口告诉给发送方,让发送方按自己的接收情况来发送数据,避免发送方发送的数据过快,导致接收方处理不过来
TCP 协议拥塞控制怎么实现的?
答:
TCP协议的拥塞控制主要通过五个算法来实现:慢启动、拥塞避免、超时重传、快速重传 和 快速恢复- 慢启动:发送方开始时设置一个较小的拥塞窗口大小,在每收到一个对新的报文段的确认后,每当成功发送跟拥塞窗口大小等量的数据后,拥塞窗口大小就会翻倍,以指数方式增长,直到拥塞控制窗口达到慢启动门限
- 拥塞避免:当窗口大小达到慢启动门限后,就进入拥塞避免阶段,每当成功发送跟拥塞窗口大小等量的数据后,拥塞窗口大小就会增加一个报文段的大小,以线性方式增长
- 拥塞发生:随着发送速率慢慢增长,可能网络会出现拥塞,发生了数据包丢失,这时候就需要重传数据重传机制主要有两种,一个是超时重传和快速重传
- 超时重传:当发生了超时重传,慢启动门限会设置为拥塞窗口的一半,并且将拥塞窗口恢复为初始值,接着就重新开始慢启动,发送速率就会瞬间下降了很多
- 快速重传和快速恢复:当发送方连续收到三个重复确认时,就认为发生了丢包,这时候拥塞窗口会减少到原来的一半,然后慢启动门限设置为减少后的拥塞窗口大小,然后进入到快速恢复阶段,这时候会把拥塞控制窗口+3,3 的意思是确认有 3 个数据包被收到了,然后重传丢失的报文,如果收到重传丢失报文的
ACK后,将拥塞窗口设置为慢启动门限,这样就直接进入拥塞避免,继续增大发送速率
- 这些拥塞控制算法,可以让
TCP协议能够根据网络状况动态调整发送速率,避免因为过大的流量导致网络拥赛
补充:
慢启动 → 拥塞避免 → 超时重传 → 慢启动:

慢启动 → 拥塞避免 → 快速重传 → 快速恢复 → 拥塞避免:

TCP 的延迟应答和累计应答是什么?
答:
TCP的延迟应答 是指接收方不立即发送ACK确认接收到的数据,而是延迟一段时间后再发送ACK。这样可以等待是否有更多的数据要发送,从而减少ACK报文的数量,提高网络利用率TCP的累计应答 是指接收方可以一次性确认接收到多个连续的数据包,而不是每收到一个数据包就发送一个ACK。这样可以减少ACK报文的数量,提高网络效率
补充:
延迟应答:TCP 在接收到对端的报文后并不会立即发送 ACK,而是等待一段时间发送 ACK,以便将 ACK 和要发送的数据一块发送,好处是能减少 ACK 报文的数量,提高网络利用率。延迟时间不能无限延长,否则对方端会认为丢包超时而造成超时重传。Linux 采用动态调节算法来确定等待的时间。延迟应答如下图:

累计应答:接收方可以一次性确认接收到多个连续的数据包,而不是每收到一个数据包就发送一个 ACK。这样可以减少 ACK 报文的数量,提高网络效率。累计应答如下图:

TCP 场景问题
TCP 拆包沾包原因是什么?怎么解决?
答:
- 我的理解
TCP是一个面向字节流协议,并不关心数据包的边界- 如果发送的数据包超过
MSS大小或者接收窗口大小后,会被拆分多个TCP段发送,这时候站在应用层的角度,就是一个完整的数据包被拆开了 - 如果发送的数据包太小,
TCP还有一个Nagle算法,会把多个小数据包堆积成一个TCP段发送,这时候就会感觉数据包是粘合一起发送的
- 如果发送的数据包超过
- 其实我认为,
TCP拆包沾包并不是TCP的问题,只是因为TCP的特性,才出现的现象,所以要解决拆包和沾包,主要是在应用层进行处理的,比方说有这些解决方案:- 固定消息长度的方式,每个数据报文都需要一个固定的长度。当接收方累计读取到固定长度的报文后,就认为已经获得一个完整的消息。当发送方的数据小于固定长度时,则需要空位补齐。但是缺点也非常明显,无法很好设定固定长度的值,如果长度太大会造成字节浪费,长度太小又会影响消息传输,所以在一般情况下消息定长法不会被采用
- 特定分隔符的方式,可以在每次发送报文的尾部加上特定分隔符,接收方就可以根据特殊分隔符进行消息拆分。比方说,
HTTP请求报文就是通过空白行的方式,分隔了请求头和请求体。这种方案需要注意的是分隔符的选择一定要避免和消息体中字符相同,以免冲突 - 消息长度 + 消息内容的方式,消息头中存放消息的总长度,例如:使用 4 字节的
int值记录消息的长度,消息体实际的二进制的字节数据。接收方在解析数据时,首先读取消息头的长度字段Len,然后紧接着读取长度为Len的字节数据,该数据即判定为一个完整的数据报文,这个方案项目开发中最常用的一种方法,因为使用方式非常灵活,且不会存在消息定长法和特定分隔符法的明显缺陷。当然在消息头中不仅只限于存放消息的长度,而且可以自定义其他必要的扩展字段,例如:消息版本、算法类型等
详细链接:[06 粘包拆包问题:如何获取一个完整的网络包?](https://learn.lianglianglee.com/专栏/Netty 核心原理剖析与 RPC 实践-完/06 粘包拆包问题:如何获取一个完整的网络包?.md)
TCP 的 keepalive 了解吗?说一说它和 HTTP 的 keepalive 的区别?
答:
HTTP的Keep-Alive是叫HTTP长连接,该功能是由应用程序实现的,可以使得用同一个TCP连接来发送和接收多个HTTP请求和应答,减少了HTTP短连接带来的多次TCP连接建立和释放的开销TCP的Keepalive是叫TCP保活机制,该功能是由内核实现的,当客户端和服务端双方长达一定时间没有进行数据交互时,内核为了确保该连接是否还有效,就会发送探测报文,来检测对方是否还在线,然后来决定是否要关闭该连接
补充:
实现的层面不同:
HTTP的Keep-Alive,是由应用层(用户态)实现的,称为HTTP长连接TCP的Keepalive,是由TCP层(内核态)实现的,称为TCP保活机制
详细链接:4.15 TCP Keepalive 和 HTTP Keep-Alive 是一个东西吗? | 小林coding
MTU是啥?MSS是啥?
答:
MTU 是一个网络包的最大长度,一般是 1500 字节,MSS 是除去 IP 包和 TCP 包的数据的最大长度,IP 层如果超过 MTU 大小就会分片,TCP 如果有超过 MSS的应用数据就要分段
补充:

MTU:一个网络包的最大长度,以太网中一般为 1500 字节。当IP层有一个超过MTU大小的数据要发送,那么IP层就要进行分片,把数据分片成若干片,保证每一个分片都小于MTUMSS:除去IP和TCP头部之后,一个网络包所能容纳的TCP数据的最大长度。当TCP层有一个超过MSS大小的应用数据,那么TCP层就要针对应用层数据进行分片,把数据分片成若干片,保证每一个分片都小于MSS
IP层会分片,为什么TCP层还需要MSS呢?
答:
- 如果交给
IP来进行分片,如果某一个IP分片丢失了,整个IP报文的所有分片都得重传。因为IP层本身没有超时重传机制,它由传输层的TCP来负责超时和重传 - 当某一个
IP分片丢失后,接收方的IP层就无法组装成一个完整的TCP报文(头部 + 数据),也就无法将数据报文送到TCP层,所以接收方不会响应ACK给发送方,因为发送方迟迟收不到ACK确认报文,所以会触发超时重传,就会重发整个TCP报文(头部 +数据) - 应用层的数据在
TCP层经过MSS分片之后,每一个分片都具备TCP头部信息,这样经过MSS分片后的报文,如果某一个丢失了,只需要重传这一个丢失的TCP报文就可以了,而不用重传所有的分片,大大增加了重传的效率
补充:
- 当
IP层有一个超过MTU大小的数据(IP头部 +TCP头部 +TCP数据)要发送,那么IP层就要进行分片,把数据分片成若干片,保证每一个分片都小于MTU。把一份IP数据报进行分片以后,由目标主机的IP层来进行重新组装后,再交给上一层TCP传输层 - 这看起来井然有序,但这存在隐患的,那么当如果一个
IP分片丢失,整个IP报文的所有分片都得重传,因为IP层本身没有超时重传机制,它由传输层的TCP来负责超时和重传。当某一个IP分片丢失后,接收方的IP层就无法组装成一个完整的 TCP 报文(头部 + 数据),也就无法将数据报文送到TCP层,所以接收方不会响应ACK给发送方,因为发送方迟迟收不到ACK确认报文,所以会触发超时重传,就会重发「整个TCP报文(头部 +数据)」 - 因此,可以得知由
IP层进行分片传输,是非常没有效率的所以,为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,当TCP层发现数据超过MSS时,则就先会进行分片,当然由它形成的IP包的长度也就不会大于MTU,自然也就不用IP分片了 - 经过
TCP层分片后,如果一个TCP分片丢失后,进行重发时也是以MSS为单位,而不用重传所有的分片,大大增加了重传的效率
一个服务端进程最多可以建立多少条 TCP 连接?
答:
- 一条
TCP连接是通过 源IP地址、目的IP地址、源端口、目的端口 这四个信息唯一确定的。服务端进程通常是会固定监听一个端口,等待客户端的连接请求,现在假设服务端的IP地址和 端口号 都是不变,那么 一个服务端进程最大能支持的理论连接数 等于 客户端的IP数量 * 客户端的端口数量,也就是 2 的 48 次方个连接数量 - 这个只是一个理论值,实际上服务端还会受系统资源的限制,比如:文件描述符的最大数量、CPU和内存资源
补充:
-
TCP是通过 四元组 唯一确认一条TCP连接的
-
源
IP地址和目的IP地址的字段(32 位)是在IP头部中,作用是定位网络中的主机。源端口和目的端口的字段(16 位)是在TCP头部中,作用是告诉TCP协议应该把报文发给哪个进程。服务端通常固定在某个本地端口上监听,等待客户端的连接请求。比如:我网站的服务端是nginx,监听了80端口
-
那么假设服务端的
IP地址和端口号不变,客户端IP和端口是可变的,一个服务端进程最大能支持的理论连接数:*一个服务端进程最大能支持的理论连接数 = 客户端的 IP 数量 客户端的端口数量 -
对 IPv4,客户端的
IP数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是一个服务端进程最大能支持的理论连接数为 2 的 48 次方 -
实际上服务端最大并发
TCP连接数远不能达到理论上限,会受以下因素影响: -
文件描述符限制,每个
TCP连接都是一个文件,如果文件描述符被占满了,会发生Too many open files。Linux对可打开的文件描述符的数量分别作了三个方面的限制:- 系统级:当前系统可打开的最大数量,通过
cat /proc/sys/fs/file-max查看 - 用户级:指定用户可打开的最大数量,通过
cat /etc/security/limits.conf查看 - 进程级:单个进程可打开的最大数量,通过
cat /proc/sys/fs/nr_open查看
- 系统级:当前系统可打开的最大数量,通过
-
内存限制,每个
TCP连接都要占用一定内存,操作系统的内存是有限的,如果内存资源被占满后,会发生OOM
详细链接:腾讯三面:一台服务器,最大支持的TCP连接数是多少?
一个机器最多可以建立多少条 TCP 连接?
答:
- 一条
TCP连接是由四元组组成的,服务器设备上可以有多个进程监听多个端口,然后如果服务器所有端口都被用来监听的话,理论上最大可以建立的TCP连接数 等于 客户端IP数 x 客户端端口数 x 服务端端口数,也就是2^32 x 2^16 x 2^16 - 上面这个只是理论值,实际中由于服务器硬件资源的限制是无法达到的,比如:内存资源的限制,我之前了解到每一条静止的
TCP连接内存占用大概3.3K,如果服务器的物理内存是4G,那么最大只能建立 100 万左右(4GB/3.3KB)的连接了
详细链接:漫画 | 一台Linux服务器最多能支撑多少个TCP连接?、漫画 | 花了七天时间测试,我彻底搞明白了 TCP 的这些内存开销! - 知乎
如果已经建立了连接,但是服务端突然出现断电了会发生什么?
答:
服务端突然断电的后:
- 如果客户端接下来会发送数据,那么由于服务端断电了,客户端已发送的数据就没办法得到确认,于是就会发生超时重传,重传次数达到上限之后,客户端就会断开
TCP连接了 - 如果客户端接下来不会再发送数据,那么要看客户端有没有开启
TCP保活机制:- 如果没有开启的话,客户端的
TCP状态将一直保持不变 - 如果有开启了
TCP保活机制,双方超过一段时间没有进行数据交互的话,内核就会触发TCP保活机制,定时发送探测报文,因为服务端断电了,客户端发送的探测报文,都不会得到响应,那么探测次数达到上限,还未收到响应的话,客户端就会断开TCP连接了
- 如果没有开启的话,客户端的
补充:
分情况讨论:
- 客户端会发送数据的情况
- 客户端不会发送数据的情况
- 客户端没有开启
TCP保活机制的情况 - 客户端有开启
TCP保活机制的情况
- 客户端没有开启
详细链接:4.12 TCP 连接,一端断电和进程崩溃有什么区别? | 小林coding
如果已经建立了连接,但是服务端的进程崩溃会发生什么?
答:
服务端进程崩溃的话,内核会负责回收服务端进程的资源,会发送 FIN 报文,和客户端进行四次挥手断开连接
补充:
TCP 的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有 TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成 TCP 四次挥手的过程
TCP 中 SYN 洪水是什么?如何防止?
答:
SYN洪水攻击就是攻击者伪造大量不同IP地址的SYN报文发送给服务端,服务端每收到SYN报文后,会把还没完成连接建立的socket,存放在tcp半连接队列,然后响应syn-ack报文,但是这些IP地址都是不存在的,这样服务端就无法收到第三次握手,这样就会导致tcp半连接队列被占满了,占满后,服务端就无法再建立tcp连接了,不能给正常的用户提供服务了- 解决的方式,我觉得最好的是开启
tcp的syn_cookie机制,它可以在服务端第二次握手的时候,生成一个伪随机的序列号,用于验证客户端的SYN包。只有在客户端回应服务器的ACK包时,服务器才会分配资源,所以可以在不使用SYN半连接队列的情况下成功建立连接,相当于绕过了SYN半连接来建立连接。其次的话,可以通过调整内核参数来增大半连接队列的大小,以及减少syn+ack重传的次数来避免SYN洪水攻击
补充:
TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同 IP 地址的 SYN 报文,服务端每接收到一个报文,就进入 SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知 IP 主机的 ACK 应答,久而久之就会占满服务端的 TCP 半连接队列,使得服务端不能为正常用户服务

解决方式:
- 开启
tcp_syncookies功能,开启syncookies功能就可以在不使用SYN半连接队列的情况下成功建立连接,相当于绕过了SYN半连接来建立连接 - 增大半连接队列,通过增大
net.ipv4.tcp_max_syn_backlog,增大listen()函数中的backlog,增大net.core.somaxconn,这三个参数来增大半连接队列 - 通过减少
tcp_synack _retries参数来减少SYN+ACK重传次数,当服务端受到SYN攻击时,就会有大量处于SYN_RECV状态的TCP连接,处于这个状态的TCP会重传SYN+ACK,当重传超过次数达到上限后,就会断开连接。那么针对SYN攻击的场景,我们可以减少SYN+ACK的重传次数,以加快处于SYN_RECV状态的TCP连接断开
详细链接:SYN 洪水 DDoS 攻击 | Cloudflare
网络层
ping 的工作原理说一下?
答:
ping 是通过 ICMP 协议来实现的,ping 的时候,会发送类型为回送请求的 ICMP 报文,对方接收到之后,就会回复类型为回送应答的 ICMP 报文
补充:

ping 命令是用来探测目标 ip 地址是否可以访问:

ping命令执行的时候,源主机首先会构建一个ICMP回送请求消息数据包,由ICMP协议将这个数据包连同服务端IP一起交给IP层,IP层将以服务端IP作为目的地址,本机IP地址作为源地址,协议字段设置为 1,再加上一些其他控制信息,构建一个IP数据包;然后加入MAC头;如果在本地ARP映射表中查找出服务端IP所对应的MAC地址,则可以直接使用,如果没有,则需要发送ARP协议查询MAC地址。获得MAC地址后,由数据链路层构建一个数据帧,目的地址是IP层传过来的MAC地址,源地址则是本机的MAC地址;还要附加上一些控制信息,依据以太网的介质访问规则将它们传送出去- 目的收到这个数据帧后,先检查它的目的
MAC地址,并和本机的MAC地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将IP数据包从帧中提取出来,交给本机的IP层。IP层检查后,将有用的信息提取后交给ICMP协议。主机 B 会构建一个ICMP回送响应消息数据包,回送响应数据包的类型字段为 0,序号为接收到的请求数据包中的序号,然后再发送出去给主机A - 在规定的时间内,源主机如果没有接到
ICMP的应答包,则说明目标主机不可达;如果接收到了ICMP回送响应消息,则说明目标主机可达
详细链接:5.2 ping 的工作原理 | 小林coding
交换机和路由器有什么区别?
答:
- 交换机工作在
MAC层,称为二层网络设备,主要处理数据帧的转发和交换,交换机会根据MAC地址来转发数据包,实现局域网内设备之间的通信 - 路由器工作在
IP层,称为三层网络设备,主要负责IP数据包的转发和路由选择,路由器会根据IP地址来转发数据包,实现不同网络之间的通信
补充:
- 网络层级不一样
- 功能不一样
什么是 IP 地址?
答:
IP 地址是用于在计算机网络上唯一标识和定位网络中的设备,IP 地址允许计算机在网络上相互通信和交换数据,在 TCP/IP 协议中,IP 地址与 MAC 地址结合使用,实现了设备之间的通信和数据传输
补充:
IP地址是用于在网络中唯一标识和定位设备的一种地址,IP地址是网络层协议中使用的一种地址,它分为IPv4地址和IPv6地址两种类型IPv4地址:IPv4地址是 32 位的二进制地址,通常用点分十进制表示,如:192.168.1.1。IPv4地址由四个8位字节组成,每个字节范围从0到255之间,共计可表示约42亿个不同的地址。然而,由于IPv4地址资源有限,目前已经出现了地址枯竭的问题IPv6地址:为了解决IPv4地址资源枯竭的问题,IPv6地址被引入并取代了IPv4地址。IPv6地址是 128 位的地址,采用冒号分隔的八组十六进制数表示,如:2001:0db8:85a3:0000:0000:8a2e:0370:7334。IPv6地址提供了极其庞大的地址空间,理论上可以支持几乎无限数量的设备连接到互联网
IP地址的作用是在互联网上唯一标识一个设备或主机,使得数据包能够准确地被发送到目的地。在TCP/IP协议中,IP地址与MAC地址结合使用,实现了设备之间的通信和数据传输
什么是 mac 地址?
答:
MAC 地址是在数据链路层中使用的标识符,只在局域网范围内有效。在互联网通信中,数据包最终是通过 IP 地址来路由和传递的,而在局域网中则是通过 MAC 地址来实现设备之间的直接通信。MAC 地址与 IP 地址结合起来,共同协助实现了数据在网络中的正确传输和交换
补充:
MAC地址是网络设备在数据链路层中使用的物理地址,用于唯一标识网络设备。每个网络设备都有一个唯一的MAC地址,通常由 48 位二进制数表示,分为 6 个十六进制数对,用冒号或短线分隔,如:00:1A:2B:3C:4D:5EMAC地址主要用于通过局域网传输数据时,帮助网络设备进行识别和寻址。与IP地址不同,MAC地址是固定的且与硬件设备绑定,不会因为设备连接到不同网络而改变。当数据包在局域网内传输时,源设备将目标设备的MAC地址作为目标地址写入数据包头部,以确保数据包能够准确地从发送者传输到接收者- 需要注意的是,
MAC地址是在数据链路层中使用的标识符,只在局域网范围内有效。在互联网通信中,数据包最终是通过IP地址来路由和传递的,而在局域网中则是通过MAC地址来实现设备之间的直接通信。MAC地址与IP地址结合起来,共同协助实现了数据在网络中的正确传输和交换
IP地址和MAC地址有什么区别?
答:
IP地址用于在 网络中 唯一标识和定位设备,它是在网络层使用的地址,用于实现不同网络之间的通信MAC地址用于在 局域网中 唯一标识和定位设备,它是在数据链路层使用的地址,用于实现局域网内设备之间的通信
详细链接:2.2 键入网址到网页显示,期间发生了什么? | 小林coding、3.7 MAC地址、IP地址以及ARP协议(1) — MAC地址_哔哩哔哩_bilibili
为什么有了IP地址,还需要MAC地址?
答:
- 只有
MAC,没有IP,网卡的实现上极其困难。如果只使用MAC地址的话,路由器就需要记住每个MAC地址所在的子网是哪一个,而世界上有 2 的 48 次方个MAC地址,这就意味着即使我们给每个MAC地址只留 1 字节的储存空间,每个路由器也需要 256 TB 的内存,这显然是不可能实现的 - 只有
IP,没有MAC,IP地址的局限。IP地址是要设备上线以后,才能根据他进入了哪个子网来分配的,在设备还没有IP地址的时候(或者分配IP地址的过程中),还需要用MAC地址来区分不同的设备,并根据MAC地址通信
补充:
可以从只有 mac 没有 ip 会有什么问题,只有 ip 没有 mac 会有什么问题来回答
NAT是什么协议?
答:
NAT协议在网络层工作,会将私有IP地址转换为公网IP地址,这样可以实现局域网的设备与互联网其他设备的通信NAT协议比较常见的转换操作是端口转换,多个私有IP地址可以共享一个公网IP地址,通过端口来区分不同的私有IP地址。所以,NAT协议的优势在于可以节省公共IP地址资源,因为多个内部设备可以共享同一个公共IP地址
补充:
- 图中有两个客户端
192.168.1.10和192.168.1.11同时与服务器183.232.231.172进行通信,并且这两个客户端的本地端口都是1025 - 此时,两个私有
IP地址都转换IP地址为公有地址120.229.175.121,但是以不同的端口号作为区分。于是,生成一个NAPT路由器的转换表,就可以正确地转换地址跟端口的组合,令客户端A、B能同时与服务器之间进行通信

192.168.1.100/24 中的斜杠代表什么意思?
答:
- 斜杠(
/)后面的数字表示子网掩码的位数- 比如:
192.168.1.100/24中的斜杠后面的数字24表示子网掩码的位数,子网掩码用于划分IP地址中的网络部分和主机部分。将子网掩码和IP地址进行 与 运算,就可以得到网络号 - 具体来说,
192.168.1.100/24表示前 24 位是网络部分,后 8 位是主机部分
- 比如:
补充:
-
主要关注网络号和主机号的概念,
-
a.b.c.d/x,其中/x表示前 x 位属于网络号,x 的范围是 0 ~ 32 比如:10.100.122.2/24,这种地址表示形式就是CIDR,/24表示前24位是网络号,剩余的8位是主机号
-
还有另一种划分网络号与主机号形式,那就是子网掩码,掩码的意思就是掩盖掉主机号,剩余的就是网络号
-
将子网掩码和
IP地址按位计算AND,就可得到网络号
-
网络攻击问题
DNS 劫持是什么?
答:
当我们访问网站的时候, 实际上是会先进行域名解析得到网站服务器的 IP 地址,然后才进行后续的访问。DNS 劫持利用了这个过程中的漏洞,攻击者在 DNS 服务器上篡改 DNS 解析结果,将域名解析到攻击者控制的恶意服务器上,这时候我们访问的域名就被重定向到恶意网站上
补充:
DNS 劫持就是黑客劫持了 DNS 服务器,篡改了 DNS 解析结果,将 client 请求的域名解析到错误的 IP 地址上,让真实服务器拿不到请求,更多发生在诱导、钓鱼、广告植入、诈骗等诸多场景

- 解决办法:手动更换公共
DNS服务器,绕过被劫持的DNS服务器
详细链接:【硬核科普】能上QQ但是打不开网页?详解DNS服务,DNS解析,DNS劫持和污染_哔哩哔哩_bilibili
DNS 污染是什么?
答:
DNS 污染就是得到了一个虚假的结果,攻击者监听 DNS 查询,一旦发现查询的域名与自己是匹配的,就把自己伪装成目标域名服务器,然后返回虚假的结果给用户,这样用户域名解析的结果就是错误的,无法和正确的目标服务器 IP 进行通信
补充:
DNS 污染是一种让一般用户由于得到虚假目标主机 IP 而不能与其通信的方法,是一种 DNS 缓存投毒攻击(DNS cache poisoning)
- 工作方式是:由于通常的
DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是 无连接不可靠 的协议,因此DNS的查询非常容易被篡改,通过对UDP端口53上的DNS查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者 返回虚假结果

DNS污染症状:目前一些在被禁止访问的网站基本都是通过DNS污染来实现的,例如:YouTube、facebook等网站- 解决办法:
- 绕过被污染的非权威
DNS服务器,直接访问干净的公共DNS服务器 - 在本机直接绑定
hosts,绕过DNS解析过程(但由于IP地址会变更,故本机的hosts也需要不断更新)
- 绕过被污染的非权威
详细链接:DNS污染和DNS劫持 - 简书
简述 DDOS 攻击原理,如何防范它?
答:
DDOS攻击就是用大量的僵尸计算机对服务器发送大量的请求,让服务器的带宽、CPU和内存耗尽,让服务器超载后,无法再对外提供正常的服务DDOS攻击大体分为网络层攻击和应用层攻击,攻击应用层的方式比如有:DNS洪水攻击,攻击传输层的方式比如有:SYN洪水攻击、UDP洪水攻击。- 我觉得可以通过这几个方面防御
DDOS攻击:- 限制单个
IP地址的请求频率,并且对异常流量的IP地址,拉黑名单,配置防火墙规则,阻止恶意流量请求 - 增加用户验证机制,使用验证码、人脸识别等方式,增加用户验证的难度,减少恶意请求的影响
- 花钱买可靠的
DDoS防护服务提供商,他们具备强大的网络基础设施和专业的防护技术,能够识别和过滤掉恶意流量,确保正常的服务运行
- 限制单个
什么是 XSS 攻击?如何防止?
答:
XSS攻击叫 跨站点脚本攻击, 攻击方式是攻击者在一些可以评论或者发帖的网站,发布一些恶意脚本代码,然后被服务端保存了,后面访问的网站的时候,浏览器会执行了该恶意脚本,这样攻击者就可以窃取用户的敏感信息了- 要防止
XSS攻击的话,可以通过这些方式:- 输入验证和过滤:过滤一些特殊的字符,比如:
javascript脚本中的<>进行转移<>再进行存储,这样就能有效的进行xss攻击的预防 - 使用
HTTP-only Cookie:将敏感信息存储在HTTP-only Cookie中,限制JavaScript的访问权限,防止恶意脚本窃取用户的Cookie信息
- 输入验证和过滤:过滤一些特殊的字符,比如:
补充:
- 存储型
XSS攻击又称为持久性跨站点脚本攻击,通常攻击者将代码存储到漏洞服务器中,用户浏览相关页面发起攻击 - 攻击步骤:
- 攻击者将恶意脚本代码上传或存储到漏洞服务器
- 服务器把恶意脚本保存到服务器
- 当正常客户访问服务器时,服务器会读取恶意数据并且直接使用
- 服务器会返回含有恶意脚本的页面
- 实际案例:
- 譬如发帖中发出包含恶意代码的内容,其他内容访问到该内容后,满足特定条件后条件即触发
- 需要后台不过滤信息,并且前端展示时也不过滤信息
- 注意:这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等
详细链接:XSS 跨站脚本攻击 - JavaScript Guidebook
什么是 CSRF 攻击?如何防止?
答:
CSRF叫 跨站点请求伪造攻击,攻击形式是:用户先登录银行A网站,这时候就获得了A网站的Cookie,然后不小心访问了一个恶意B网站,B网站会让用户向银行A网站发起一个转账请求,由于用户端有了银行A网站的Cookie,这时候有可能就会转账成功,造成并非本人意愿的操作结果- 防御
CSRF攻击的话,可以有这些方式:- 同源检测:在服务器端对请求进行同源检测,只接受来自同一域名下的请求。这可以通过检查请求头中的
Referer字段或者Origin字段来实现 - 使用验证码:对于敏感操作,要求用户输入验证码进行验证,以防止自动化脚本发起的恶意请求
- 使用
CSRF令牌:在用户执行敏感操作时,要求用户提交一个CSRF令牌。该令牌是一个随机生成的字符串,存储在用户的会话中,并且在每个请求中都要验证该令牌的有效性。攻击者无法伪造正确的CSRF令牌,从而防止CSRF攻击
- 同源检测:在服务器端对请求进行同源检测,只接受来自同一域名下的请求。这可以通过检查请求头中的
补充:
-
CSRF叫 跨站点请求伪造攻击,攻击者通过跨站请求,以合法的用户身份进行非法操作如转账交易、发表评论等。其核心是利用了浏览器Cookie或服务器的Session策略,盗取用户的身份信息
-
在打开
A网站 的情况下,另开Tab页面打开恶意网站B,此时在B页面的恶意意图下,浏览器发起一个对网站A的HTTP请求,因为之前A网站 已经打开了,浏览器存有A网站中的Cookie或其他用于身份认证的信息,这一次被 恶意意图的请求,将会自动带上这些信息,这将会导致身份劫持,造成并非本人意愿的操作结果 -
而对应
CSRF攻击的防御策略有:表单token、验证码、Referer检测等
详细链接:CSRF 跨站请求伪造攻击 - JavaScript Guidebook
什么是 SQL 注入攻击?如何防止?
答:
SQL注入攻击是攻击者在HTTP请求中注入恶意SQL语句,让服务端构造执行SQL语句时,恶意的SQL被一起构造了,然后在数据库中执行,这样就可能对数据库造成全量数据拉取、删除、更新等敏感的操作- 预防
SQL注入攻击,可以通过这几个方式:- 使用参数化查询或预编译语句:使用参数化查询或预编译语句来构建和执行
SQL查询。这样可以将用户输入的数据作为参数传递给查询,而不是将其直接拼接到SQL语句中,参数化查询可以防止恶意代码的注入 - 输入验证和过滤:对用户输入的数据进行验证和过滤,确保只接受合法的输入,可以使用白名单过滤、正则表达式验证或者编码转义等技术来防止恶意代码的注入
- 最小权限原则:在数据库中为应用程序使用最小权限的数据库账户,这样即使发生SOL注入攻击,攻击者也只能在该账户的权限范围内进行操作,减少损失
- 使用参数化查询或预编译语句:使用参数化查询或预编译语句来构建和执行
补充:
SQL 注入攻击指的是攻击者在 HTTP 请求中注入恶意 SQL 命令,服务器用请求参数构造数据库 SQL 命令时,恶意 SQL 被一起构造,并在数据库中执行,以便得到数据库中的感兴趣的数据或对数据库进行读取、修改、删除、插入等敏感的操作,从而导致数据被随意篡改

详细链接:什么是 SQL 注入? | Cloudflare、实战1:如何用 PREPARE 防止 SQL 注入_SQL 入门教程-慕课网
网络编程
Socket 网络编程对应 TCP 三次握手的环节?
答:
- 服务端首先会通过
bind函数给socket绑定 端口 和IP地址,然后调用listen函数,进行监听,然后调用accpet函数等待客户端建立连接 - 当客户端调用
connect函数的时候,内核会随机生成初始化序号,放到TCP报文头部的序号字段中,同时把 SYN 标志设置为1,这样就表示SYN报文。接着把这个SYN报文发送给服务端,之后客户端处于SYN_SENT状态 - 服务端收到
SYN报文后,首先服务端也会随机生成初始化序号,放到TCP报文头部的序号字段中,然后对客户端的 初始化序号+1 作为 确认号,放到TCP报文头部的确认应答字段中,并将SYN和ACK标志设置为 1,这样就表示SYN_ACK报文,然后把该报文发给客户端,之后服务端处于SYN_RCVD状态 - 客户端收到服务端
SYN_ACK报文后,客户端会回一个ACK确认报文,该报文的确认号是 服务端的初始化序号+1,并且ACK标志会设置为 1,之后客户端处于ESTABLISHED状态,这时候connect函数就返回了 - 服务端收到
ACK确认报文后,服务端也进入处于ESTABLISHED状态,这时候accpet函数就返回已建立连接的socket,后续与客户端进行通信,就是对这个socket进行读写操作

建立TCP连接,Socket 在 TCP 握手哪个阶段可以拿到连接?
答:
需要完成三次握手后,服务端才能通过 accpet 函数得到已经建立 TCP 连接的 socket

listen 的参数 backlog 意义是什么?
答:
backlog 参数的大小,是指定 TCP 全连接队列大小的参数之一。内核会从内核参数 somaxconn 大小和backlog 参数大小之间取一个最小值作为 TCP 全连接队列大小
补充:
Linux内核中会维护两个队列:
- 半连接队列(
SYN队列):接收到一个SYN建立连接请求,处于SYN_RCVD状态 - 全连接队列(
Accpet队列):已完成TCP三次握手过程,处于ESTABLISHED状态

1 | int listen (int socketfd, int backlog) |
- 参数一
socketfd:为socketfd文件描述符 - 参数二
backlog:这参数在历史版本有一定的变化在- 早期
Linux内核backlog是SYN队列大小,也就是未完成的队列大小。在Linux内核2.2之后,backlog变成accept队列,也就是已完成连接建立的队列长度,所以现在通常认为backlog是accept队列 - 但是上限值是内核参数
somaxconn的大小,也就说accpet队列长度=min(backlog, somaxconn)
- 早期
详细链接:4.4 TCP 半连接队列和全连接队列 | 小林coding
当客户端多次发送连接,服务器没有accept,客户端会出现什么现象?
答:
我觉得会导致客户端无法和服务端建立 TCP 连接,因为如果服务端没有执行 accpet 的话,那么已经建立连接的 socket 会堆积到 TCP 全连接队列,如果 TCP 全连接队列占满了,服务端收到新的客户端 SYN 报文的时候,内核就会丢弃 SYN 报文
补充:

四次挥手对应 socket 中通信的部分,其中哪些是用户调用,哪些是内核完成的?
答:
第一次挥手和第三次挥手的 FIN 报文,都需要客户端或者服务端调用 close 函数触发的,第二次和四次挥手的 ACK 就是 内核 来完成
补充:

如果客户端和服务端同时调用了 close() 会发生什么?
答:
双方会同时发送 FIN 报文,由于双方在等待 ACK 报文的过程中,都等来了 FIN 报文,这是一种新情况,所以连接会进入一种叫做 CLOSING 的新状态,它替代了 FIN_WAIT_2 状态。接着,双方内核回复 ACK 确认对方发送通道的关闭后,进入 TIME_WAIT 状态,等待 2MSL 的时间后,连接自动关闭
补充:
由于 TCP 是双全工的协议,所以是会出现两方同时关闭连接的现象,也就是同时发送了 FIN 报文

怎么知道客户端关闭连接?
答:
- (正常断开情况)如果客户端正常断开连接的情况下,会发起了第一次挥手
FIN报文,服务端收到后,内核会插入一个文件结束符EOF到接收缓冲区中,应用程序可以通过read调用来感知这个FIN报文,如果read返回 0 了,就代表客户端关闭连接了 - (异常断开情况)如果客户端突然宕机了,服务端无感知客户端已经不存在了,如果接下来服务端不会在发送任何数据的话超过一段时间后,
TCP就会开启保活机制,来探测客户端是否还存活,如果最终判断到客户端不存在了,服务端这边也会自动释放连接






