计算机网络 面试题目总结
1 基础
1.1 计算机网络体系结构
计算机网络体系结构通过将复杂的网络通信分解成不同的层次,来标准化交互的过程。常见的模型包括 OSI 七层模型、TCP/IP 四层模型和五层体系结构。OSI 是理论上的网络通信模型,TCP/IP 是实际应用层面上的网络通信模型,五层结构是为了方便理解和记忆。
1.2 说说 OSI 七层模型?
OSI七层模型是一个用来描述计算机网络体系结构的标准模型。它将网络通信划分为七个抽象层,每一层都负责特定的功能,从物理连接到应用程序。这些层从下到上分别是:
- 物理层(Physical Layer):负责传输比特流,并管理物理介质。
- 数据链路层(Data Link Layer):处理帧的传输,通过物理地址进行寻址。
- 网络层(Network Layer):负责数据包的路由和转发,实现不同网络之间的通信。
- 传输层(Transport Layer):提供端到端的可靠数据传输,包括错误检测、流量控制和分段重组。
- 会话层(Session Layer):负责建立、管理和终止会话连接,以及数据的同步和恢复。
- 表示层(Presentation Layer):处理数据的格式化和表示,确保不同系统的数据格式能够互相理解。
- 应用层(Application Layer):提供用户与网络服务的接口,包括各种应用程序和协议,如HTTP、FTP和SMTP。
1.3 说说 TCP/IP 四层模型?
TCP/IP 合并了 OSI 的部分层次,专注于高效的网络通信实践,更具实用性。
- 网络接口层(Network Interface Layer):对应于 OSI 模型的物理层和数据链路层。负责数据帧的物理传输,包括硬件地址寻址(MAC 地址),数据封装和解封装,错误检测和纠正等。
- 网际层(Internet Layer)对应于 OSI 模型的网络层。主要协议是 IP,负责数据包的寻址和路由。这一层还包括 ICMP 协议。
- 传输层(Transport Layer):对应于 OSI 模型的传输层。负责提供端到端的数据传输服务,包括数据分割、流量控制、错误恢复等。主要的协议有 TCP 和 UDP
- 应用层(Application Layer):对应于 OSI 模型的会话层、表示层和应用层。包括所有与网络有关的高级协议,如 HTTP、FTP、SMTP 等。
1.4 说说五层体系结构?
是对 OSI 和 TCP/IP 的折衷,它保留了 TCP/IP 的实用性,同时提供了比四层模型更细致的分层,便于教学和理解网络的各个方面。
- 应用层:作为网络服务和最终用户之间的接口。它提供了一系列供应用程序使用的协议,如 HTTP(网页)、FTP(文件传输)、SMTP(邮件传输)等。使用户的应用程序可以访问网络服务。
- 传输层:提供进程到进程的通信管理,这一层确保数据按顺序、无错误地传输。主要协议包括 TCP 和 UDP。
- 网络层:负责数据包从源到目的地的传输和路由选择,包括跨越多个网络(即互联网)。它使用逻辑地址(如 IP 地址)来唯一标识设备。路由器是网络层设备。
- 数据链路层:确保从一个节点到另一个节点的可靠、有效的数据传输。交换机、网桥是数据链路层设备。
- 物理层:电缆、光纤、无线电频谱、网络适配器等。
1.5 说一下每一层对应的网络协议有哪些?
OSI七层网络模型 | TCP/IP四层模型 | 对应的网络协议 |
---|---|---|
应用层 | 应用层 | HTTP、DNS、FTP、NFS、WAIS、SMIP、Telnet、SNMP |
表示层 | 应用层 | TIFF、GIF、JPEG、PICT |
会话层 | 应用层 | RPC、SQL、NFS、NetBIOS、names、AppleTalk |
传输层 | 传输层 | TCP、UDP |
网络层 | 网络层 | IP、ICMP、ARP、RAPP、RIP、IPX |
数据链路层 | 网络接口层 | FDDI、Frame Relay、HDLC、PPP |
物理层 | 网络接口层 | EIA/TIA-232、EIA/TIA-499 |
1.6 数据在各层之间是怎么传输的呢?
对于发送方而言,从上层到下层层层包装,对于接收方而言,从下层到上层,层层解开包装。
- 发送方的应用进程向接收方的应用进程传送数据
- AP 先将数据交给本主机的应用层,应用层加上本层的控制信息 H5 就变成了下一层的数据单元
- 传输层收到这个数据单元后,加上本层的控制信息 H4,再交给网络层,成为网络层的数据单元
- 到了数据链路层,控制信息被分成两部分,分别加到本层数据单元的首部(H2)和尾部(T2)
- 最后的物理层,进行比特流的传输
这个过程类似写信,写一封信,每到一层,就加一个信封,写一些地址的信息。到了目的地之后,又一层层解封,传向下一个目的地。
2 网络综合
2.1 从浏览器地址栏输入 URL 到显示主页的过程
从在浏览器地址栏输入 URL 到显示主页的过程包括多个步骤,涵盖了 DNS 解析、TCP 连接、发送 HTTP 请求、服务器处理请求并返回 HTTP 响应、浏览器处理响应并渲染页面等多个环节。
- DNS 解析:浏览器发起一个 DNS 请求到 DNS 服务器,将域名解析为服务器的 IP 地址。
- TCP 连接:浏览器通过解析得到的 IP 地址与服务器建立 TCP 连接(通常是通过 443 端口进行 SSL 加密的 HTTPS 连接)。这一步涉及到 TCP 的三次握手过程,确保双方都准备好进行数据传输。
- 发送 HTTP 请求:浏览器构建 HTTP 请求消息,包括请求行(如 GET / HTTP/1.1)、请求头(包含用户代理、接受的内容类型等信息)和请求体(如果有);将请求发送到服务器。
- 服务器处理请求:服务器接收到 HTTP 请求后,根据请求的资源路径,经过后端处理(可能包括数据库查询等),生成 HTTP 响应消息;响应消息包括状态行(如 HTTP/1.1 200 OK)、响应头(内容类型、缓存控制等信息)和响应体(请求的资源内容)。
- 浏览器接收 HTTP 响应:浏览器接收到服务器返回的 HTTP 响应数据,开始解析响应体中的 HTML 内容;然后构建 DOM 树、解析 CSS 和 JavaScript 文件等,最终渲染页面。
- 断开连接:TCP 四次挥手,连接结束
2.2 各个过程都使用了哪些协议?
- DNS:获取域名对应的IP
- TCP:与服务器建立连接和断开连接
- IP:使用TCP协议时,网络层需要使用IP协议。
- OPSF:IP数据包在路由器之间,路由选择使用OPSF协议
- ARP:路由器再与服务器通信时,需要将IP地址转换为MAC地址,需要使用ARP协议
- HTTP:TCP连接建立完成之后,使用HTTP协议传递HTTP报文
2.3 说说 DNS 的解析过程?
DNS 的全称是 Domain Name System,也就是域名解析系统,它可以将域名映射到对应的 IP 地址上,比如说我们访问 www.google.com
,实际上访问的是谷歌的一台服务器,它的 IP 地址是 xxx.xxx.xxx.xxx
。可以通过 IP 地址直接访问服务器,但不方便记忆,所以就有了域名系统。域名到 IP 之间的映射,就需要 DNS 来完成。
假设我们在浏览器地址栏里键入了www.google.com
:
- 浏览器会首先检查自己的缓存中是否有这个域名对应的 IP 地址,如果有,直接返回;如果没有,进入下一步。
- 检查本地 DNS 缓存是否有该域名的记录。
- 如果没有,向根域名服务器发送请求,根域名服务器将请求指向更具体的服务,如
com
顶级域名服务器。 - 顶级域名服务器再将请求指向权限域名服务器,通常由域名注册机构直接管理,所以机构会提供对应的 DNS 解析服务,将域名和谷歌服务器绑定起来。
- 最终,浏览器使用获得的 IP 地址发起一个 HTTP 请求到目标服务器,然后该服务器返回所请求的网页内容。
2.4 说说 WebSocket 与 Socket 的区别?
Socket 其实就是等于 IP 地址 + 端口 + 协议。具体来说,Socket 是一套标准,它完成了对 TCP/IP 的高度封装,屏蔽网络细节,以方便开发者更好地进行网络编程。
WebSocket: 是一种网络协议,属于应用层协议。它是在单个 TCP 连接上进行全双工通信的协议,设计用于浏览器和服务器之间的通信,用来解决 http 不支持持久化连接的问题。
Socket 一个是网络编程的标准接口,而 WebSocket 则是应用层通信协议。
Socket工作在传输层,可以基于 TCP 或 UDP 协议。它需要开发者自己处理数据的发送和接收、连接的建立和断开等低层次的细节。
WebSocket工作在应用层,依赖于 TCP 协议。WebSocket 在初次连接时通过 HTTP 请求进行握手,一旦连接建立,后续的数据传输都在 WebSocket 协议上进行,浏览器和服务器都可以主动向对方发送数据,保持连接直到显式断开。
Socket传输的是字节流,需要开发者自行定义数据的格式和协议。WebSocket传输的是文本帧或二进制帧,协议本身定义了消息的格式,能够直接发送 JSON 或二进制数据,方便开发者使用。
2.5 说一下你了解的端口及对应的服务?
端口 | 服务 | 用途 |
---|---|---|
21 | FTP(文件传输协议) | 用于在计算机之间传输文件 |
22 | SSH | 用于远程登录、文件传输和命令行界面交互 |
23 | Telnet(远程登录服务) | 允许用户从一台计算机登录到另一台计算机 |
53 | DNS域名解析服务 | 将域名转换为IP地址以便访问网站 |
80 | HTTP超文本传输协议 | 用于在万维网上交换信息 |
443 | HTTPS | 提供安全的HTTP通信 |
1080 | SOCKS | 用于在计算机之间安全地传输数据。它通过代理服务器来隐藏原始的IP地址和端口号,从而提供匿名性和安全性 |
3306 | MySQL默认端口号 | 用于MySQL数据库服务器上的数据访问 |
3 HTTP
3.1 说说 HTTP 常用的状态码及其含义?
HTTP 响应状态码是由服务器返回给客户端,用于表示对请求的响应结果。
这些状态码分为五个不同的类别,每个类别用一个数字开头,共有三位数:
- 1XX:信息性状态码,临时的响应,客户端应继续请求。
- 2XX:成功状态码,请求已成功被服务器接收。
- 3XX:重定向状态码,用来重定向。
- 4XX:客户端错误状态码,请求可能出错。
- 5XX:服务器错误状态码,服务器在尝试处理请求时发生了错误。
常见HTTP状态码如下:
状态码 | 含义 |
---|---|
101 Switching Protocols | 切换请求协议 |
200 OK | 请求成功 |
301 Moved Permanently | 请求资源永久移动,返回新URI |
302 Found | 请求资源临时移动,继续使用原有URI |
400 Bad Request | 客户端请求的语法错误,服务端无法理解 |
401 Unauthorized | 当前请求需要认证 |
403 Forbidden | 服务器拒绝请求,客户端无权访问该资源 |
404 Not Found | 请求的资源在服务器上不存在 |
500 Internal Server Error | 服务器内部错误 |
3.2 HTTP 有哪些请求方式?
HTTP 协议定义了多种请求方式,用以指示请求的目的。常见的请求方式有 GET、POST、DELETE、PUT。在正确实现的条件下,GET、HEAD、PUT 和 DELETE 等方法都是幂等的,而 POST 方法不是(每次发送 POST 请求,服务器可能会生成新的资源 ID 或处理生成的唯一值(如订单号、事务 ID)。因此,重复发送 POST 请求会导致创建多个不同的资源或多次执行某个操作)。
- GET:请求检索指定的资源。应该只用于获取数据,并且是幂等的,即多次执行相同的 GET 请求应该返回相同的结果,并且不会改变资源的状态。
- POST:向指定资源提交数据,请求服务器进行处理(如提交表单或上传文件)。数据被包含在请求体中。可能会创建新的资源或修改现有资源。
- DELETE:删除指定的资源。
- PUT:用于替换指定的资源。如果指定的资源不存在,创建一个新资源。
- HEAD:类似于 GET 请求,但只请求响应头信息,不会返回响应体。常用于检查资源是否存在以及资源的元数据(如检查链接是否有效)。
- OPTIONS:请求服务器返回该资源所支持的所有 HTTP 方法。常用于检查服务器的功能或资源的通信选项。
- PATCH:用于对资源进行部分修改,而不是完全替代资源。
- TRACE:回显服务器收到的请求,主要用于测试和诊断。
- CONNECT:用于将请求连接转换为透明的 TCP/IP 隧道,通常用于 HTTPS 通过代理服务器的请求。
3.3 HTTP 的 GET 方法可以实现写操作吗?
严格来说,HTTP 的 GET 方法不应该用于实现写操作,因为它设计为一种安全的、幂等的读取操作。GET 请求的主要作用是从服务器获取资源,而不应对服务器上的数据进行任何修改。
但是,实际上,有些 Web 应用可能会滥用 GET 请求进行写操作,例如通过在 URL 中传递参数来修改服务器上的数据。这种做法是不推荐的,主要有以下几个原因:
- 安全性:GET 请求会将参数包含在 URL 中,这使得敏感数据容易暴露,且容易受到攻击(如 CSRF 攻击)。
- 缓存问题:GET 请求通常会被缓存,而缓存的 GET 请求不应引发服务器状态的变化。如果 GET 请求用于写操作,可能会导致缓存的副作用。
- 幂等性和安全性:HTTP 标准要求 GET 请求是幂等的(多次相同的请求应产生相同的结果)和安全的(不应对服务器状态产生副作用)。使用 GET 实现写操作违背了这些原则。
3.4 说一下 GET 和 POST 的区别?
从 HTTP 报文层面:
GET 请求:将请求参数放在 URL 中,因此 URL 的长度有限制。数据在 URL 中传输,不安全,容易被窃取。
POST 请求:将请求参数放在请求体中,没有长度限制。数据在报文体中传输,相对更安全。
从幂等性和安全性:
GET 请求:
- 幂等性:多次请求不会改变服务器状态,每次结果相同。
- 安全性:不会对服务器资源进行修改。
POST 请求:
不幂等:每次请求可能导致服务器状态变化(如创建资源)。
不安全:请求会对服务器资源进行修改。
从其他层面:
- GET 请求:能够被缓存,减轻服务器负担。能够保存在浏览器的浏览记录里。URL 可以保存为浏览器书签。
- POST 请求:不能被缓存,不保存在浏览器历史记录里。URL 不便于保存为书签。
3.5 GET 的长度限制是多少?
HTTP 中的 GET 方法是通过 URL 传递数据的,但是 URL 本身其实并没有对数据的长度进行限制,真正限制 GET 长度的是浏览器。
例如 IE 浏览器对 URL 的最大限制是 2000 多个字符,大概 2kb 左右,像 Chrome、Firefox 等浏览器支持的 URL 字符数更多,其中 FireFox 中 URL 的最大长度限制是 65536 个字符,Chrome 则是 8182 个字符。
这个长度限制也不是针对数据部分,而是针对整个 URL。
3.6 HTTP 请求的过程与原理?
HTTP 全称是超文本传输协议(HyperText Transfer Protocol),是一个基于请求与响应模式的应用层协议,基于 TCP/IP 协议传输数据。
HTTP 遵循标准的客户端-服务器模型,客户端打开连接以发出请求,然后等待它收到服务器端响应。
- 在浏览器输入 URL 后,浏览器首先会通过 DNS 解析获取到服务器的 IP 地址,然后与服务器建立 TCP 连接。
- TCP 连接建立后,浏览器会向服务器发送 HTTP 请求。
- 服务器收到请求后,会根据请求的信息处理请求。
- 处理完请求后,服务器会返回一个 HTTP 响应给浏览器。
- 浏览器收到响应后,会根据响应的信息渲染页面。然后,浏览器和服务器断开 TCP 连接。
客户端发送一个请求到服务器,服务器处理请求并返回一个响应。这个过程是同步的,也就是说,客户端在发送请求后必须等待服务器的响应。在等待响应的过程中,客户端不会发送其他请求。
3.7 说一下 HTTP 的报文结构?
HTTP 的报文结构可以分为两类:请求报文和响应报文。两者在结构上相似,都包含了起始行、头部和消息正文。
请求报文结构
请求行 (Request Line)
- 方法 (Method):如 GET、POST、PUT、DELETE 等。
- 请求目标 (Request-URI):即请求的资源路径。
- HTTP 版本 (HTTP-Version):如 HTTP/1.1。
请求头部 (Request Headers)
- 包含多个首部字段,每个字段由字段名和字段值组成。
- 用于提供客户端信息、请求的资源信息等。
常见请求头:
Host
:请求的主机名和端口。User-Agent
:发起请求的客户端信息。Accept
:客户端可接受的响应内容类型。Content-Type
:请求体的媒体类型。Authorization
:认证信息。
空行:用于分隔请求头部和请求主体。
请求主体 (Request Body):包含实际要发送给服务器的数据,仅在 POST、PUT 等方法中存在。
1 2 3 4
GET /index.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 Accept: text/html
响应报文结构
状态行 (Status Line)
HTTP 版本 (HTTP-Version):如 HTTP/1.1。
状态码 (Status Code):如 200、404、500 等。
原因短语 (Reason-Phrase):对状态码的简短描述。
响应头部 (Response Headers)
- 包含多个首部字段,每个字段由字段名和字段值组成。
- 用于提供服务器信息、响应的资源信息等。
常见响应头:
Date
:响应生成的日期和时间。Content-Type
:响应体的媒体类型。Content-Length
:响应体的长度。Set-Cookie
:设置 HTTP Cookie。
空行:用于分隔响应头部和响应主体。
响应主体 (Response Body):包含实际要返回给客户端的数据。
1 2 3 4 5 6 7 8 9 10
HTTP/1.1 200 OK Date: Mon, 27 Jul 2009 12:28:53 GMT Content-Type: text/html Content-Length: 138 <html> <body> <h1>Hello, World!</h1> </body> </html>
3.8 URI 和 URL 有什么区别?
属性 | URI | URL |
---|---|---|
定义 | 统一资源标识符,用于标识一个资源 | 统一资源定位符,提供资源的定位方法 |
组成部分 | [scheme:][//authority][path][?query][#fragment] | scheme://authority/path[?query][#fragment] (必须包含scheme(协议),authority(域名/IP),路径) |
例子 | urn:isbn:0451450523 (为URN,不是URL,但是URI) | https://www.example.com/index.html |
子集 | 可以是 URL 或 URN | 是 URI 的子集 |
3.9 说下 HTTP1.0,1.1,2.0 的区别?
HTTP1.0 默认短连接,HTTP 1.1 默认长连接,HTTP 2.0 采用多路复用。
特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2.0 |
---|---|---|---|
连接管理 | 短连接(默认每个请求/响应对后都关闭连接) | 长连接(默认 keep-alive) | 多路复用(同一连接多请求) |
Host 头部 | 不支持 | 支持 | 支持 |
缓存控制 | 简单的 Expires 头部 | 复杂的 Cache-Control 头部 | 同 HTTP/1.1 |
传输编码 | 无 | 支持分块传输编码 | 二进制分帧 |
请求方法 | GET, POST | GET, POST, PUT, DELETE, OPTIONS 等 | 同 HTTP/1.1 |
头部压缩 | 无 | 无 | HPACK 压缩(减少了冗余头部信息的带宽消耗) |
服务器推送 | 无 | 无 | 支持 |
流优先级 | 无 | 无 | 支持 |
3.10 HTTP/3 了解吗?
HTTP/2.0 基于 TCP 协议,而 HTTP/3.0 则基于 QUIC 协议,Quick UDP Connections,直译为快速 UDP 网络连接。
基于 TCP 的 HTTP/2.0,尽管从逻辑上来说,不同的流之间相互独立,不会相互影响,但在实际传输的过程中,数据还是要一帧一帧的发送和接收,一旦某一个流的数据有丢包,仍然会阻塞在它之后传输的流数据。
而基于 UDP 的 QUIC 协议可以更彻底解决了 HTTP/2 中的队头阻塞问题,让不同的流之间真正的实现相互独立传输,互不干扰。同时,QUIC 协议在传输的过程中就完成了 TLS 加密握手,更直接了。
目前使用最广泛的是哪个HTTP版本还是是 HTTP/2,在 2022 年 1 月达到峰值,占所有网站的 46.9%。
3.11 HTTP 如何实现长连接?在什么时候会超时?
什么是 HTTP 的长连接?
- HTTP 分为长连接和短连接,本质上说的是 TCP 的长短连接。TCP 连接是一个双向的通道,它是可以保持一段时间不关闭的,因此 TCP 连接才具有真正的长连接和短连接这一说法。
- TCP 长连接可以复用一个 TCP 连接,来发起多次的 HTTP 请求,这样就可以减少资源消耗,比如一次请求 HTML,如果是短连接的话,可能还需要请求后续的 JS/CSS。
通过在头部(请求和响应头)设置 Connection 字段指定为keep-alive
,HTTP/1.0 协议支持,但是是默认关闭的,从 HTTP/1.1 以后,连接默认都是长连接。
在什么时候会超时呢?
HTTP 一般会有 httpd 守护进程,里面可以设置 keep-alive timeout,当 tcp 连接闲置超过这个时间就会关闭,也可以在 HTTP 的 header 里面设置超时时间
TCP 的 keep-alive 包含三个参数,支持在系统内核的 net.ipv4 里面设置;当 TCP 连接之后,闲置了 tcp_keepalive_time,则会发生侦测包,如果没有收到对方的 ACK,那么会每隔 tcp_keepalive_intvl 再发一次,直到发送了 tcp_keepalive_probes,就会丢弃该连接。
1 2 3
tcp_keepalive_intvl = 15 tcp_keepalive_probes = 5 tcp_keepalive_time = 1800
3.12 说说 HTTP 与 HTTPS 有哪些区别?
- HTTPS 是 HTTP 的增强版,在 HTTP 的基础上加入了 SSL/TLS 协议,确保数据在传输过程中是加密的。SSL/TLS 需要向 CA(证书权威机构)申请数字证书,用于验证服务器的身份。
- HTTP 的默认端⼝号是 80,URL 以
http://
开头;HTTPS 的默认端⼝号是 443,URL 以https://
开头。
3.13 为什么要用 HTTPS?解决了哪些问题?
使用 HTTPS 主要是为了解决 HTTP 传输过程中的一些安全问题,因为 HTTP 是明文传输,所以 HTTPS 在 HTTP 的基础上加入了 SSL/TLS 协议。
HTTPS 主要解决了以下几个问题:
- 窃听风险:第三方可以截获传输的数据包,获取敏感信息。
- 篡改风险:第三方可以在传输过程中篡改数据包,修改数据。
- 冒充风险:第三方可以冒充服务器,与客户端通信。
3.14 HTTPS 工作流程是怎样的?
HTTPS 的连接建立在 SSL/TLS 握手之上,工作流程如下图所示:
如果通信内容被截取,但由于没有会话密钥,所以无法解密。当通信结束后,连接会被关闭,会话密钥也会被销毁,下次通信会重新生成一个会话密钥。
HTTPS 在不同阶段会使用不同的加密方式:
- 非对称加密:在握手阶段使用,特别是在密钥交换过程中。非对称加密使用公钥和私钥,其中公钥可以公开,私钥保密。客户端使用公钥加密信息,服务器使用私钥解密。
- 对称加密:在完成握手后,所有的数据传输都使用对称加密。对称加密使用相同的密钥进行加密和解密,这种加密方式比非对称加密更快。
3.15 HTTPS 会加密 URL 吗?
HTTPS 通过 SSL/TLS 协议确保了客户端与服务器之间交换的数据被加密,这包括 HTTP 头部和正文。而 URL 是 HTTP 头部的一部分,因此这部分信息也是加密的。但因为涉及到 SSL 握手的过程,所以域名信息会被暴露出来,需要注意。
3.16 客户端怎么去校验证书的合法性?
首先,所有的证书都是由 CA 机构签发的,CA 机构是一个受信任的第三方机构,它会对证书的申请者进行身份验证,然后签发证书,它具有极高的可信度。
客户端(通常是浏览器,通常会集成 CA 的公钥信息)在校验证书的合法性时,主要通过以下步骤来校验证书的合法性。
- 浏览器会读取证书的所有者、有效期、颁发者等信息,先校验网站域名是否一致,然后校验证书的有效期是否过期;
- 浏览器开始查找内置的 CA,与服务器返回证书中的颁发者进行对比,确认是否为合法机构;
- 如果是,从内部植入的 CA 公钥解密 Certificate 的 Signature 内容,得到⼀个 Hash 值 H2;
- 使⽤同样的 Hash 算法获取证书的 Hash 值 H1,⽐较 H1 和 H2,如果值相同,则为可信赖的证书,否则告警。
3.17 如何理解 HTTP 协议是无状态的?
这个无状态
的的状态
值的是什么?是客户端的状态,所以字面意思,就是 HTTP 协议中服务端不会保存客户端的任何信息。
比如当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。
那有什么办法记录状态呢?
主要有两个办法,Session 和 Cookie。
3.18 说说 Session 和 Cookie 有什么联系和区别?
- Cookie 是保存在客户端的一小块文本串的数据。客户端向服务器发起请求时,服务端会向客户端发送一个 Cookie,客户端就把 Cookie 保存起来。在客户端下次向同一服务器再发起请求时,Cookie 被携带发送到服务器(通过 HTTP 请求头的
Cookie
字段在客户端和服务器之间传递)。服务端可以根据这个 Cookie 判断用户的身份和状态。Cookie可以设置过期时间。如果不设置过期时间,则 Cookie 在会话结束(浏览器关闭)时失效。可以通过设置Expires
或Max-Age
属性来定义 Cookie 的持久性。 - Session 指的就是服务器和客户端一次会话的过程。它是另一种记录客户状态的机制。不同的是 cookie 保存在客户端浏览器中,而 session 保存在服务器上(客户端只保存 Session ID)。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 session。客户端浏览器再次访问时只需要从该 session 中查找用户的状态。Session一般在用户会话结束时(例如关闭浏览器、超时)失效。服务器端可以配置 Session 的过期时间。
Session 和 Cookie 联系:依赖于 Cookie 来传递 Session ID(通常是服务器在创建 Session 时设置一个 Cookie 来存储 Session ID)。
Session 和 Cookie 的使用场景也不同:
- Cookie:适用于存储用户偏好、登录状态等较小的数据,可以跨页面持久化数据。常用于记录用户信息、跟踪用户行为等。
- Session:适用于存储用户会话中的临时信息,如购物车、登录状态等。更适合需要较高安全性的场景,因为数据存储在服务器端。
分布式环境下 Session 怎么处理呢?
分布式环境下,客户端请求经过负载均衡,可能会分配到不同的服务器上,假如一个用户的请求两次没有落到同一台服务器上,那么在新的服务器上就没有记录用户状态的 Session。
可以使用 Redis 等分布式缓存来存储 Session,在多台服务器之间共享。
客户端无法使用 Cookie 怎么办?
有可能客户端无法使用 Cookie,比如浏览器禁用 Cookie,或者客户端是安卓、IOS 等等。
这时候怎么办?SessionID 怎么存?怎么传给服务端呢?首先是 SessionID 的存储,可以使用客户端的本地存储,比如浏览器的 sessionStorage。
接下来怎么传呢?
- 拼接到 URL 里:直接把 SessionID 作为 URL 的请求参数
- 放到请求头里:把 SessionID 放到请求的 Header 里,比较常用。
4 TCP
4.1 详细说一下 TCP 的三次握手机制?
TCP(Transmission Control Protocol)是一个面向连接的、可靠的、基于字节流的传输层协议。TCP 通过三次握手机制来建立连接,确保双方准备就绪并能可靠地进行通信。以下是三次握手的详细过程:
第一次握手
- 客户端:发送一个带有 SYN 标志的 TCP 报文段(称为 SYN 报文段),并选择一个初始序列号
seq = x
。 - 服务器:收到这个 SYN 报文段后,服务器处于 “SYN_RCVD” 状态。
- 目的:客户端通知服务器它希望建立连接,并告知服务器自己的初始序列号。
报文内容:
1
客户端 --> 服务器: SYN, seq = x
- 客户端:发送一个带有 SYN 标志的 TCP 报文段(称为 SYN 报文段),并选择一个初始序列号
第二次握手
- 服务器:服务器收到 SYN 报文段后,回复一个带有 SYN 和 ACK 标志的 TCP 报文段(称为 SYN-ACK 报文段)。该报文段中包含服务器选择的初始序列号
seq = y
,以及对客户端序列号x
的确认ack = x + 1
。 - 客户端:收到这个 SYN-ACK 报文段后,客户端处于 “ESTABLISHED” 状态。
- 目的:服务器告诉客户端,它的连接请求被接受了,并通知客户端自己的初始序列号。
报文内容:
1
服务器 --> 客户端: SYN, ACK, seq = y, ack = x + 1
- 服务器:服务器收到 SYN 报文段后,回复一个带有 SYN 和 ACK 标志的 TCP 报文段(称为 SYN-ACK 报文段)。该报文段中包含服务器选择的初始序列号
第三次握手
- 客户端:客户端收到 SYN-ACK 报文段后,回复一个带有 ACK 标志的 TCP 报文段(称为 ACK 报文段)。该报文段中包含对服务器序列号
y
的确认ack = y + 1
。 - 服务器:收到这个 ACK 报文段后,服务器处于 “ESTABLISHED” 状态,连接建立完成。
- 目的:客户端确认收到了服务器的同步应答,完成三次握手,建立连接。
报文内容:
1
客户端 --> 服务器: ACK, seq = x + 1, ack = y + 1
- 客户端:客户端收到 SYN-ACK 报文段后,回复一个带有 ACK 标志的 TCP 报文段(称为 ACK 报文段)。该报文段中包含对服务器序列号
4.2 TCP 握手为什么是三次,为什么不能是两次?不能是四次?
使用三次握手可以建立一个可靠的连接。这一过程的目的是确保双方都知道对方已准备好进行通信,并同步双方的序列号,从而保持数据包的顺序和完整性。
两次握手无法确保连接的可靠性。具体原因如下:
- 旧的重复报文干扰:在两次握手情况下,旧的 SYN 报文可能会被错误地当作新的连接请求。如果服务器发送 SYN-ACK 报文后客户端没有响应,服务器会认为连接失败,但实际上客户端可能已经收到了 SYN-ACK 报文,这样就会导致服务器资源浪费和连接不一致。
- 确认机制不完整:两次握手不能保证双方都能正确接收到对方的确认报文。服务器无法确认客户端是否收到了自己的 SYN-ACK 报文,而客户端也无法确认服务器是否收到了自己的 SYN 报文。
四次握手在正常情况下是多余的,会增加连接建立的复杂性和开销。三次握手已经足够保证连接的可靠性和正确性:
- 增加复杂性和开销:四次握手会增加额外的一个报文传输,使得连接建立的过程变得复杂,不必要地增加了传输的延迟和开销。
- 三次握手足够可靠:三次握手已经可以确保双方都能确认连接的建立,并且可以避免旧的重复报文的干扰,再增加一次握手并不会带来额外的安全性或可靠性提升。
4.3 三次握手中每一次没收到报文会发生什么情况?
在TCP三次握手的过程中,每一次没收到报文都会触发重传机制,并最终导致连接建立失败。具体情况如下:
第一次握手:客户端发送 SYN 报文
情况:如果客户端发送的 SYN 报文没有收到服务器的 SYN-ACK 报文(比如报文丢失或服务器没有响应)。
处理:客户端会进行超时重传。客户端在发送 SYN 报文后会启动一个定时器,如果在一定时间内没有收到服务器的响应(SYN-ACK 报文),客户端会重传 SYN 报文。
结果:重传次数达到一定次数(通常是三次)后,客户端会放弃连接,报错并关闭连接请求。
第二次握手:服务器发送 SYN-ACK 报文
情况:如果服务器发送的 SYN-ACK 报文没有收到客户端的 ACK 报文(比如报文丢失或客户端没有响应)。
处理:服务器会进行超时重传。服务器在发送 SYN-ACK 报文后也会启动一个定时器,如果在一定时间内没有收到客户端的 ACK 报文,服务器会重传 SYN-ACK 报文。
结果:重传次数达到一定次数后,服务器会放弃连接,报错并关闭连接请求。
第三次握手:客户端发送 ACK 报文
情况:如果客户端发送的 ACK 报文没有收到服务器的确认(ACK 报文本身一般不会单独确认,但此处假设服务器未能进入 ESTABLISHED 状态)。
处理:服务器会因为没有收到 ACK 报文而保持在 SYN-RECEIVED 状态,并可能最终超时并关闭连接。
结果:客户端会认为连接已经建立,并进入 ESTABLISHED 状态,但如果服务器超时关闭连接,客户端在尝试发送数据时会发现连接无法使用,从而报错并关闭连接。
4.4 第二次握手传回了 ACK,为什么还要传回 SYN?
ACK 标志是为了告诉客户端,它发送的 SYN 报文已经被服务器正确接收。
而传回 SYN 是为了告诉客户端,服务器也希望建立连接,并且响应的确实是客户端发送的报文。
4.5 第 3 次握手可以携带数据吗?
第 3 次握手是可以携带数据的。此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,它已经建立连接成功,并且确认服务端的接收和发送能力是正常的。
但实际应用中通常不会携带数据,因为在第三次握手中发送数据可能会引发安全和可靠性问题。此时连接还未完全建立,发送数据可能导致数据丢失或安全漏洞。
第一次握手不能携带数据是出于安全的考虑,因为如果允许携带数据,攻击者每次在 SYN 报文中携带大量数据,就会导致服务端消耗更多的时间和空间去处理这些报文,会造成 CPU 和内存的消耗。
4.6 说说半连接队列和 SYN Flood 攻击的关系?
TCP 进入三次握手前,服务端会从 CLOSED 状态变为 LISTEN 状态, 同时在内部创建了两个队列:半连接队列(SYN 队列)和全连接队列(ACCEPT 队列)。
半连接队列(Half-Open Connection Queue)是指在 TCP 三次握手过程中,服务器在收到客户端的 SYN 报文后,返回 SYN-ACK 报文并等待客户端的 ACK 报文确认连接的这段时间内,服务器为每个未完成的连接分配的资源队列。
SYN Flood 攻击是指攻击者发送大量的 SYN 报文请求与服务器建立连接,但在服务器返回 SYN-ACK 报文后,攻击者不发送最终的 ACK 报文完成握手。这样,服务器的半连接队列会被大量未完成的连接占满,导致服务器资源耗尽,无法处理正常的连接请求,进而造成拒绝服务(Denial of Service,DoS)。
因此,SYN Flood 攻击的核心在于利用半连接队列的有限资源,通过大量伪造的连接请求使服务器无法处理合法用户的连接。
那有什么应对方案呢?
主要有 syn cookie 和 SYN Proxy 防火墙等。
- syn cookie:在收到 SYN 包后,服务器根据一定的方法,以数据包的源地址、端口等信息为参数计算出一个 cookie 值作为自己的 SYNACK 包的序列号,回复 SYN+ACK 后,服务器并不立即分配资源进行处理,等收到发送方的 ACK 包后,重新根据数据包的源地址、端口计算该包中的确认序列号是否正确,如果正确则建立连接,否则丢弃该包。
- SYN Proxy 防火墙:服务器防火墙会对收到的每一个 SYN 报文进行代理和回应,并保持半连接。等发送方将 ACK 包返回后,再重新构造 SYN 包发到服务器,建立真正的 TCP 连接。
- 缩短 SYN-ACK 超时时间:调整系统的 SYN-ACK 超时时间,使未完成的连接请求能够更快地被清理出队列。
- 分布式拒绝服务防护(DDoS Protection Services):使用专业的 DDoS 防护服务,如 Cloudflare、Akamai 等,这些服务可以在网络边缘过滤恶意流量,减轻服务器的压力。
4.7 说说 TCP 四次挥手的过程?
TCP 四次挥手是指 TCP 连接终止时所进行的四个步骤,数据传输结束之后,通信双方都可以主动发起断开连接请求,这里假定客户端发起(通常是客户端),具体过程如下:
- 第一次挥手:FIN 报文:
- 客户端发送一个 FIN 报文段,表明它已经完成了数据发送,请求关闭连接。客户端进入 FIN_WAIT_1 状态。
- 报文段格式:
FIN=1, seq=x
。
- 第二次挥手:ACK 报文:
- 服务器接收到 FIN 报文后,返回一个 ACK 报文段,确认收到了关闭请求。发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态。
- 报文段格式:
ACK=1, ack=x+1
。 - 此时,服务器可能还需要继续发送数据,因此连接处于半关闭状态。
- 第三次挥手:FIN 报文:
- 服务端在完成数据发送后,发送一个 FIN 报文段,表明它也已经完成了数据发送,请求关闭连接。发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个 ACK。
- 报文段格式:
FIN=1, seq=y
。
- 第四次挥手:ACK 报文:
- 客户端接收到 FIN 报文后,返回一个 ACK 报文段,确认收到了关闭请求,并进入 TIME_WAIT 状态,等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
- 报文段格式:
ACK=1, ack=y+1
。 - 此时,连接正式关闭,双方都完成了连接的释放。
4.8 TCP 挥手为什么需要四次呢?。
- 关闭连接时,客户端向服务端发送
FIN
时,仅仅表示客户端不再发送数据了但是还能接收数据。 - 服务端收到客户端的
FIN
报文时,先回一个ACK
应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送FIN
报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK
和 FIN
一般都会分开发送,从而比三次握手导致多了一次。
4.9 TCP 四次挥手过程中,为什么需要等待 2MSL, 才进入 CLOSED 关闭状态?
- 为了保证客户端发送的最后一个 ACK 报文段能够到达服务端。 这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的服务端就收不到对已发送的 FIN 报文段的确认。服务端会超时重传这个 FIN 报文段,而客户端就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN 报文段。接着客户端重传一次确认,重新启动 2MSL 计时器。最后,客户端和服务器都正常进入到 CLOSED 状态。
- 防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。
为什么等待的时间是 2MSL?
MSL 是 Maximum Segment Lifetime,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。
TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是:⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间。
4.10 保活计时器有什么用?
除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer),用于在长时间闲置的 TCP 连接中检测对端是否仍然存活,并防止连接因为长时间没有活动而被认为是不活跃的而被关闭。
设想这样的场景:客户已主动与服务器建立了 TCP 连接。但后来客户端的主机突然发生故障。显然,服务器以后就不能再收到客户端发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就需要使用保活计时器了。
服务器每收到一次客户端的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若连续发送 10 个探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接。
4.11 CLOSE-WAIT
和 TIME-WAIT
的状态和意义?
CLOSE-WAIT 状态有什么意义?
服务端收到客户端关闭连接的请求并确认之后,就会进入 CLOSE-WAIT 状态。此时服务端可能还有一些数据没有传输完成,因此不能立即关闭连接,而 CLOSE-WAIT 状态就是为了保证服务端在关闭连接之前将待发送的数据处理完。
TIME-WAIT 有什么意义?
TIME-WAIT 状态发生在第四次挥手,当客户端向服务端发送 ACK 确认报文后进入 TIME-WAIT 状态。
- 防⽌旧连接的数据包
- 保证连接正确关闭
4.12 TIME_WAIT
状态过多会导致什么问题?怎么解决?
TIME_WAIT 状态过多会导致什么问题?
如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器⽅主动发起的断开请求。
什么场景下服务端会主动断开连接呢?
- HTTP 没有使用长连接
- HTTP 长连接超时
- HTTP 长连接的请求数量达到上限
过多的 TIME-WAIT 状态主要的危害有两种:
- 端口资源耗尽:每个处于
TIME_WAIT
状态的连接都会占用一个本地端口。如果TIME_WAIT
状态的连接过多,可能会导致可用的本地端口资源耗尽,新的连接请求无法分配端口,从而导致服务不可用。 - 内存和资源占用:
TIME_WAIT
状态的连接会占用一定的系统内存和资源。如果连接过多,会导致系统资源被大量占用,影响服务器的性能和其他应用的运行。
怎么解决 TIME_WAIT 状态过多?
- 服务器可以设置
SO_REUSEADDR
套接字来通知内核,如果端口被占用,但是 TCP 连接位于 TIME_WAIT 状态时可以重用端口。 - 还可以使用长连接的方式来减少 TCP 的连接和断开,在长连接的业务里往往不需要考虑 TIME_WAIT 状态。
4.13 说说 TCP 报文头部的格式?
一个 TCP 报文段主要由报文段头部(Header)和数据两部分组成。头部包含了确保数据可靠传输所需的各种控制信息,比如说序列号、确认号、窗口大小等。
|
|
- 源端口号(Source Port):16 位(2 个字节),用于标识发送端的应用程序。
- 目标端口号(Destination Port):也是 16 位,用于标识接收端的应用程序。
- 序列号(Sequence Number):32 位,用于标识从 TCP 发送者发送的数据字节流中的第一个字节的顺序号。确保数据按顺序接收。
- 确认号(Acknowledgment Number):32 位,如果 ACK 标志被设置,则该字段包含发送确认的序列号,即接收 TCP 希望收到的下一个序列号。
- 数据偏移(Data Offset):4 位,表示 TCP 报文头部的长度,用于指示数据开始的位置。
- 保留(Reserved):6 位,为将来使用预留,目前必须置为 0。
- 控制位(Flags):共 6 位,包括 URG(紧急指针字段是否有效)、ACK(确认字段是否有效)、PSH(提示接收端应该尽快将这个报文段交给应用层)、RST(重置连接)、SYN(同步序号,用于建立连接)、FIN(结束发送数据)。
- 窗口大小(Window):16 位,用于流量控制,表示接收端还能接收的数据的字节数(基于接收缓冲区的大小)。
- 校验和(Checksum):16 位,覆盖整个 TCP 报文段(包括 TCP 头部、数据和一个伪头部)的校验和,用于检测数据在传输过程中的任何变化。
- 紧急指针(Urgent Pointer):16 位,只有当 URG 控制位被设置时才有效,指出在报文段中有紧急数据的位置。
4.14 TCP 是如何保证可靠性的?
TCP(传输控制协议)通过多种机制来确保数据传输的可靠性。以下是TCP保证可靠性的主要方法:
- 连接管理(Connection Management):TCP 使用三次握手(Three-Way Handshake)建立连接和四次挥手(Four-Way Handshake)关闭连接,确保连接的建立和释放过程可靠、无误。
- 校验和(Checksum):TCP 报文段包含一个校验和字段,用于验证报文段在传输过程中是否被损坏。发送方计算并填充校验和,接收方根据接收到的数据重新计算校验和并进行验证,确保数据的完整性。
- 序列号(Sequence Numbers):TCP 为每个字节分配一个序列号。发送方和接收方使用序列号来确保数据按照正确的顺序接收并重组,防止数据丢失或重复。
- 确认应答(Acknowledgments, ACKs):TCP 使用确认应答机制来确认数据的接收。接收方在收到数据后,会发送一个带有确认号的ACK报文段,告知发送方已成功接收到的数据。这种机制确保了数据的传递和确认。
- 拥塞控制(Congestion Control):TCP 通过慢启动、拥塞避免、快重传和快恢复等算法来防止网络拥塞,保证数据传输的稳定性和可靠性。
- 流量控制(Flow Control):TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。(TCP 利用滑动窗口实现流量控制)
- 重传机制(Retransmission):发送方在发送数据后会启动一个计时器。如果在指定时间内未收到对应的ACK报文段,发送方会认为该数据包丢失并进行重传。TCP还使用快速重传机制,当收到三个重复的ACK时,立即重传相应的数据包。
- 最大消息长度(Maximum Message Length):在建立 TCP 连接的时候,双方约定一个最大的长度(MSS)作为发送的单位,重传的时候也是以这个单位来进行重传。理想的情况下是该长度的数据刚好不被网络层分块。
4.15 说说 TCP 的流量控制?
TCP 提供了一种机制,可以让发送端根据接收端的实际接收能力控制发送的数据量,以确保接收方能够及时处理数据而不会因为数据过多而溢出缓冲区,这就是流量控制。
TCP 的流量控制主要通过滑动窗口(Sliding Window)机制来实现。示例如下:
4.16 详细说说 TCP 的滑动窗口?
TCP 发送一个数据,如果需要收到确认应答,才会发送下一个数据。这样的话就会有个缺点:效率会比较低。而滑动窗口允许发送方在未接收到 ACK 确认之前可以发送多个数据段,以提高网络的利用率和传输效率,同时避免了发送方过度发送导致接收方缓冲区溢出。
TCP 滑动窗口分为两种: 发送窗口和接收窗口。发送端的滑动窗口包含四大部分,如下:
- 已发送且已收到 ACK 确认
- 已发送但未收到 ACK 确认
- 未发送但可以发送
- 未发送也不可以发送
蓝色框里就是发送窗口。SND.WND 表示发送窗口的大小,SND.NXT表示下一个发送的位置,它指向未发送但可以发送的第一个字节的序列号;SND.UNA: 一个绝对指针,它指向的是已发送但未确认的第一个字节的序列号。
接收方的滑动窗口包含三大部分,如下:
- 已成功接收并确认
- 未收到数据但可以接收
- 未收到数据并不可以接收的数据
蓝色框内,就是接收窗口。REV.WND 表示接收窗口的大小;REV.NXT表示下一个接收的位置,它指向未收到但可以接收的第一个字节的序列号。
发送方和接收方通过 ACK 确认报文段来协商窗口大小。发送方根据接收方的接收窗口大小来调整自己的发送窗口大小,以确保不会发送超出接收方能力的数据量。
4.17 了解 Nagle 算法和延迟确认吗?
Nagle 算法和延迟确认是干什么的?
当我们 TCP 报⽂的承载的数据⾮常⼩的时候,例如⼏个字节,那么整个⽹络的效率是很低的,因为每个 TCP 报⽂中都会有 20 个字节的 TCP 头部,也会有 20 个字节的 IP 头部,⽽数据只有⼏个字节,所以在整个报⽂中有效数据占有的比例就会⾮常低。
那么就出现了常⻅的两种策略,来减少⼩报⽂的传输,分别是:
- Nagle 算法:当应用程序发送数据时,Nagle 算法会先将数据放入缓冲区,并等待一定的时间(称为 Nagle 算法定时器),以便将多个小数据包合并成一个大数据包一起发送。只有当缓冲区中的数据量达到一定阈值(Nagle 算法的最小传输单元)或者定时器超时时,才会触发数据的发送。Nagle 算法主要用于避免发送大量小数据包的情况,从而减少网络的拥塞,提高网络的性能和效率。
- 延迟确认:当接收方收到数据时,不会立即发送 ACK 确认报文,而是等待一段时间(一般是等待 200 毫秒左右),以便将多个 ACK 合并成一个 ACK 一起发送。如果在延迟时间内收到新的数据包,则会立即发送 ACK 报文,以确认收到的数据。延迟确认主要用于减少确认报文的数量,避免网络中出现过多的 ACK 报文,从而减少网络的负载和提高网络的吞吐量。
一般情况下,Nagle 算法和延迟确认不能一起使用,Nagle 算法意味着延迟发,延迟确认意味着延迟接收,两个凑在一起就会造成更大的延迟,会产生性能问题。
4.18 说说 TCP 的拥塞控制?
什么是拥塞控制?不是有了流量控制吗?
前⾯的流量控制是避免发送⽅的数据填满接收⽅的缓存,但是并不知道整个⽹络之中发⽣了什么。
⼀般来说,计算机⽹络都处在⼀个共享的环境。因此也有可能会因为其他主机之间的通信使得⽹络拥堵。
在⽹络出现拥堵时,如果继续发送⼤量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是⼀重传就会导致⽹络的负担更重,于是会导致更⼤的延迟以及更多的丢包,这个情况就会进⼊恶性循环被不断地放⼤….
所以,TCP 不能忽略整个网络中发⽣的事,它被设计成⼀个⽆私的协议,当⽹络发送拥塞时,TCP 会⾃我牺牲,降低发送的数据流。
于是,就有了拥塞控制,控制的⽬的就是避免发送⽅的数据填满整个⽹络。
发送方维护一个拥塞窗口 cwnd(congestion window) 的变量,调节所要发送数据的量。
什么是拥塞窗⼝?和发送窗⼝有什么关系呢?
拥塞窗⼝ cwnd是发送⽅维护的⼀个的状态变量,它会根据⽹络的拥塞程度动态变化的。
发送窗⼝ swnd 和接收窗⼝ rwnd 是约等于的关系,那么由于加⼊了拥塞窗⼝的概念后,此时发送窗⼝的值是 swnd = min(cwnd, rwnd),也就是拥塞窗⼝和接收窗⼝中的最⼩值。
拥塞窗⼝ cwnd 变化的规则:
- 只要⽹络中没有出现拥塞, cwnd 就会增⼤;
- 但⽹络中出现了拥塞, cwnd 就减少;
拥塞控制有哪些常用算法?
拥塞控制主要有这几种常用算法:
- 慢启动:先发出少量数据,就像探路一样,先摸清当前的网络拥堵状态后,再决定按照多大的速度传送数据)
- 拥塞避免:在拥塞避免阶段,TCP的拥塞窗口以线性增长的方式增加,而不是指数级增长
- 快重传:发送方不必等待超时计时器的到期,而是立即进行快速重传,重传丢失的数据包
- 快恢复:快恢复算法用于在收到重复ACK时,迅速调整拥塞窗口大小以恢复传输速度
4.19 说说 TCP 的重传机制?
TCP 的重传机制是确保数据传输可靠性的重要部分之一。它通过在发送方定时器超时或者接收到连续的重复确认时触发,重新发送丢失或者未确认的数据段,以确保数据能够在网络中正确传输。以下是 TCP 的重传机制的主要原理:
- 超时重传:当发送方发送数据后,在等待一定时间内未收到确认 ACK 报文时,触发超时重传机制,重新发送未确认的数据段。超时时间通常根据网络往返时间(RTT)动态调整,以适应网络延迟的变化。
- 快速重传:当发送方接收到连续的重复 ACK 报文时,表明接收方已经成功接收了一些数据,但有一个或多个数据段丢失。为了尽快重传丢失的数据段,发送方立即触发快速重传机制,重新发送丢失的数据段,而不必等待超时定时器的到期。
- 带选择确认的重传(SACK):选择确认(SACK)为了解决应该重传多少个包的问题,允许接收方在确认报文中指示出连续的数据段中哪些已经成功接收,哪些丢失了。发送方可以根据 SACK 报文中指示的丢失数据段信息,选择性地进行重传,而不是重传整个窗口内的所有未确认数据段。
- 重复 SACK:是在 SACK 的基础上做了一些扩展,在接收方收到连续的重复数据段时,会生成多个相同的 SACK 报文,用于指示哪些数据段已经成功接收。主要用来告诉发送方,有哪些数据包,自己重复接受了。DSACK 的目的是帮助发送方判断,是否发生了包失序、ACK 丢失、包重复或伪重传。让 TCP 可以更好的做网络流控。
4.20 说说 TCP 的粘包和拆包?
TCP 是面向流,没有界限的一串数据。TCP 底层并不了解上层业务数据的具体含义,它会根据 TCP 缓冲区的实际情况进行包的划分。
粘包指的是在 TCP 连接中,发送方发送的多个数据包在接收方接收时被合并成一个数据包。这种情况通常发生在以下几种场景中:
- 发送方发送数据过于频繁,发送的数据量较小,多个小数据包在发送时被合并成一个数据包。Nagle 算法的作用使得发送方在网络未确认前将小数据包合并发送。
- 接收方读取数据不及时,一次性读取多个数据包。
拆包指的是一个完整的数据包在接收方接收时被拆分成了多个数据包。这种情况通常发生在以下几种场景中:
- 网络传输过程中,由于 MTU(最大传输单元)的限制,一个大的数据包被拆分成多个小的数据包进行传输。
- 待发送数据大于 MSS(最大报文长度),TCP 在传输前将进行拆包。即 TCP 报文长度 - TCP 头部长度 > MSS。
那怎么解决呢?
- 发送端将每个数据包封装为固定长度;
- 在数据尾部增加特殊字符进行分割;
- 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小;
- 设计特定的应用层协议,包含数据包头部(例如,标识符、长度字段、校验和等)和数据部分。接收方根据协议解析数据包。
4.21 如果已经建立了连接,但是服务端的进程崩溃会发生什么?服务器断电呢?
TCP 的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有 TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成 TCP 四次挥手的过程。
当服务器断电时,情况会有所不同:客户端在尝试与服务器通信时,会发现连接中断,通常会收到一个错误(如 ECONNRESET
或 ETIMEDOUT
),客户端的应用程序需要处理这个错误,并可能尝试重新建立连接或采取其他应对措施。
4.22 如果已经建立了连接,但是客户端突然出现故障了怎么办?
客户端出现故障指的是客户端的主机发生了宕机,或者断电的场景。发生这种情况的时候,如果服务端一直不会发送数据给客户端,那么服务端是永远无法感知到客户端宕机这个事件的,也就是服务端的 TCP 连接将一直处于 ESTABLISH
状态,占用着系统资源。
为了避免这种情况,TCP 搞了个保活机制。这个机制的原理是这样的:
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
4.23 服务器出现大量 CLOSE_WAIT 状态的原因有哪些?
CLOSE_WAIT 状态是【被动关闭方】才会有的状态,而且如果【被动关闭方】没有调用 close 函数关闭连接,那么就无法发出 FIN 报文,从而无法使得 CLOSE_WAIT 状态的连接转变为 LAST_ACK 状态。
所以,当服务端出现大量 CLOSE_WAIT 状态的连接的时候,说明服务端的程序没有调用 close 函数关闭连接。
我们先来分析一个普通的 TCP 服务端的流程:
- 创建服务端 socket,bind 绑定端口、listen 监听端口
- 将服务端 socket 注册到 epoll
- epoll_wait 等待连接到来,连接到来时,调用 accpet 获取已连接的 socket
- 将已连接的 socket 注册到 epoll
- epoll_wait 等待事件发生
- 对方连接关闭时,我方调用 close
可能导致服务端没有调用 close 函数的原因是:2,3,4,6步没有做
5 UDP
5.1 说说 TCP 和 UDP 的区别?
特性 | TCP | UDP |
---|---|---|
连接 | 面向连接,传输数据前需建立连接 | 无需连接,立即传输数据 |
服务对象 | 一对一的两点服务 | 支持一对一、一对多、多对多的交互通信 |
可靠性 | 可靠交付,数据无差错、不丢失、不重复、按序到达 | 尽最大努力交付,不保证可靠交付数据 |
拥塞控制、流量控制 | 有拥塞控制和流量控制机制 | 无拥塞控制和流量控制机制,发送速率不受网络拥堵影响 |
首部开销 | 首部长度较长(20 字节—60字节) | 首部只有 8 字节,且固定不变,开销较小 |
传输方式 | 字节流式传输,无边界,保证顺序和可靠 | 数据段报文传输,有边界,可能丢包和乱序 |
分片 | 在传输层进行分片,丢失分片时只重传丢失部分 | 在 IP 层进行分片,接收后在 IP 层组装再传给传输层 |
应用场景 | 文件传输、邮件传输 | 即时通讯、域名转换 |
5.2 为什么 QQ 采用 UDP 协议?
- 首先,QQ 并不是完全基于 UDP 实现。比如在使用 QQ 进行文件传输等活动的时候,就会使用 TCP 作为可靠传输的保证。
- 使用 UDP 进行交互通信的好处在于,延迟较短,对数据丢失的处理比较简单。同时,TCP 是一个全双工协议,需要建立连接,所以网络开销也会相对大。
- 如果使用 QQ 语音和 QQ 视频的话,UDP 的优势就更为突出了,首先延迟较小。最重要的一点是不可靠传输,这意味着如果数据丢失的话,不会有重传。因为用户一般来说可以接受图像稍微模糊一点,声音稍微不清晰一点,但是如果在几秒钟以后再出现之前丢失的画面和声音,这恐怕是很难接受的。
- 由于 QQ 的服务器设计容量是海量级的应用,一台服务器要同时容纳十几万的并发连接,因此服务器端只有采用 UDP 协议与客户端进行通讯才能保证这种超大规模的服务
简单总结一下:UDP 协议是无连接方式的协议,它的效率高,速度快,占资源少,对服务器的压力比较小。但是其传输机制为不可靠传送,必须依靠辅助的算法来完成传输控制。QQ 采用的通信协议以 UDP 为主,辅以 TCP 协议。
5.3 UDP 协议为什么不可靠?
UDP 在传输数据之前不需要先建立连接,远地主机的运输层在接收到 UDP 报文后,不需要确认,提供不可靠交付。总结就以下四点:
- 不保证消息交付:不确认,不重传,无超时
- 不保证交付顺序:不设置包序号,不重排,不会发生队首阻塞
- 不跟踪连接状态:不必建立连接或重启状态机
- 不进行拥塞控制:不内置客户端或网络反馈机制
5.4 DNS 为什么要用 UDP?
更准确地说,DNS 既使用 TCP 又使用 UDP。
当进行区域传送(主域名服务器向辅助域名服务器传送变化的那部分数据)时会使用 TCP,因为数据同步传送的数据量比一个请求和应答的数据量要多,而 TCP 允许的报文长度更长,因此为了保证数据的正确性,会使用基于可靠连接的 TCP。即在需要可靠传输或处理大数据包的特定场景下,DNS 也会使用 TCP 以确保传输的可靠性和完整性。
当客户端想 DNS 服务器查询域名(域名解析)的时候,一般返回的内容不会超过 UDP 报文的最大长度,即 512 字节,用 UDP 传输时,不需要创建连接,从而大大提高了响应速度,但这要求域名解析服务器和域名服务器都必须自己处理超时和重传从而保证可靠性。
5.5 你会如何设计QQ中的网络协议?
首先,我们要实现登录功能,这是使用 QQ 的第一步,为了保证账号和密码的安全性,我们可以选择 TCP + SSL/TLS 协议来进行登录。
因为 TCP 协议是一种可靠的传输协议,能够保证数据的完整性,而 SSL/TLS 能够对通信进行加密,保证数据的安全性。
接下来,我们需要考虑消息传递的实时性,如语音视频通话等,这时候我们可以选择 UDP 协议。UDP 的传输速度更快,对于实时性服务来说,速度是最重要的。
5.6 UDP如何尽量保证消息的不丢失
对于 TCP 协议来说,如果数据包在传输过程中丢失,TCP 协议会自动进行重传。
而对于 UDP 协议来说,我们可以通过应用层的重传机制来保证消息的不丢失。当接收方收到消息后,返回一个确认信息给发送方,如果发送方在一定时间内没有收到确认信息,就重新发送消息。
同时,每个消息都附带一个唯一的序列号,接收方根据序列号判断是否有消息丢失,如果发现序列号不连续,就可以要求发送方重新发送。这样还可以防止消息重复。
当然了,消息持久化也很重要,可以将消息保存在服务器或者本地的数据库中,即使在网络中断或者其他异常情况下,也能从数据库中恢复消息。
6 QUIC
6.1 QUIC是如何实现可靠传输的?(UDP如何实现可靠传输?)
把TCP可靠传输的特性(序号,确认应答,超时重传,流量控制)在应用层实现一遍。
- 基于UDP:QUIC 建立在 UDP 之上,通过在 UDP 数据报中封装自己的数据包来实现可靠传输。
- 可靠传输:QUIC 提供了类似于 TCP 的可靠传输机制,包括序列号、确认应答、重传和流量控制。
- 多路复用:QUIC 支持多条独立的流,解决了 TCP 的队头阻塞问题。
- 拥塞控制:QUIC 实现了拥塞控制算法,确保高效的数据传输。
6.2 QUIC是如何解决TCP队头阻塞问题的?
TCP的队头阻塞(Head-of-Line Blocking)问题是指在数据传输过程中,如果某个数据包丢失了,后续的数据包即使已经到达接收方,也无法被处理,因为接收方必须按顺序处理数据包。
QUIC通过以下机制解决了这个问题:
- 多路复用:QUIC允许多个独立的流在同一个连接中传输,每个流都有自己的序列号和确认机制。这意味着即使某个流的数据包丢失了,也不会影响其他流的数据传输。
- 独立流处理:接收方可以独立处理每个流的数据包,即使某个流的数据包丢失了,接收方仍然可以处理其他流的数据包,避免了队头阻塞。
6.3 QUIC是如何做流量控制的?
QUIC的流量控制机制与TCP类似,但更为灵活和高效:
- 流级别的流量控制:每个流都有自己的流量控制窗口,发送方在发送数据之前,必须确保数据大小不超过接收方为该流设定的窗口大小。
- 连接级别的流量控制:除了流级别的流量控制,QUIC还支持连接级别的流量控制,限制整个连接上的未确认数据总量,防止网络拥塞。
- 动态调整窗口大小:QUIC可以根据网络状况动态调整流量控制窗口的大小,提高数据传输的效率和适应性。
6.4 QUIC是如何迁移连接的?
基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。
那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立 TCP 连接。
而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。
QUIC 协议没有用四元组的方式来“绑定”连接,而是通过以下机制:
- 连接ID:QUIC为每个连接分配一个唯一的连接ID,连接ID与客户端和服务器的IP地址和端口无关。因此,即使客户端的IP地址或端口发生变化,只要连接ID不变,连接仍然有效。
- 路径验证:在迁移连接时,QUIC会验证新的路径是否可用,确保数据能够通过新路径传输。
- 迁移过程:当客户端检测到网络变化(例如,从WiFi切换到移动网络)时,会通知服务器新的地址和端口。服务器验证新的路径后,继续通过新的路径传输数据。
- 无缝切换:通过连接ID和路径验证机制,QUIC实现了连接的无缝迁移,避免了因网络变化导致的连接中断和数据丢失。
7 IP
7.1 IP 协议的定义和作用?
IP 协议(Internet Protocol)又被称为互联网协议,是支持网间互联的数据包协议,工作在网际层,主要目的就是为了提高网络的可扩展性。
通过网际协议 IP,可以把参与互联的,性能各异的网络看作一个统一的网络。
和传输层 TCP 相比,IP 协议是一种无连接/不可靠、尽力而为的数据包传输服务,和 TCP 协议一起构成了 TCP/IP 协议的核心。
IP 协议有哪些作用?
IP 协议主要有以下几个作用:
- 寻址和路由:在 IP 数据报中携带源 IP 地址和目的 IP 地址来表示该数据包的源主机和目标主机。IP 数据报在传输过程中,每个中间节点(IP 网关、路由器)只根据网络地址来进行转发,如果中间节点是路由器,则路由器会根据路由表选择合适的路径。IP 协议根据路由选择协议提供的路由信息对 IP 数据报进行转发,直至目标主机。
- 分段和重组:IP 数据报在传输过程中可能会经过不同的网络,在不同的网络中数据报的最大长度限制是不同的,IP 协议通过给每个 IP 数据报分配一个标识符以及分段与组装的相关信息,使得数据报在不同的网络中能够被传输,被分段后的 IP 数据报可以独立地在网络中进行转发,在达到目标主机后由目标主机完成重组工作,恢复出原来的 IP 数据报。
- 差错处理:虽然 IP 是尽力而为的协议,不保证数据报一定到达目的地,但它包含一些基本的差错处理机制,例如校验和(checksum),用于检测数据报头部的错误。
- 控制信息:IP 头部包含了多个字段,用于控制和管理数据报的传输,如生存时间(TTL,Time to Live)字段,防止数据报在网络中无限循环。
传输层协议和网络层协议有什么区别?
网络层协议负责提供主机间的逻辑通信;传输层协议负责提供进程间的逻辑通信。
7.2 IP 地址有哪些分类?
IP地址(Internet Protocol Address)是用于标识网络中设备的唯一地址。IP地址有两种版本:IPv4和IPv6。IPv4是目前最广泛使用的版本,IPv6是为解决IPv4地址耗尽问题而设计的新版本。
IPv4地址是32位长的二进制数,通常表示为四个十进制数(每个数对应8位)之间用点分隔(例如,192.168.1.1)。IPv4地址可以按其用途和结构分为A,B,C,D,E五大类:
- A 类地址 (1~126):以 0 开头,网络号占前 8 位,主机号占后面 24 位,主要用于大型网络;
- B 类地址 (128~191):以 10 开头,网络号占前 16 位,主机号占后面 16 位,主要用于中型网络;
- C 类地址 (192~223):以 110 开头,网络号占前 24 位,主机号占后面 8 位,主要用于小型网络;
- D 类地址 (224~239):以 1110 开头,保留为多播地址,用于一对多通信;
- E 类地址 (240~255):以 1111 开头,保留位为将来使用,用于实验和研究。
IPv4有以下特殊地址:
- 本地回环地址(Loopback Address):127.0.0.0 到 127.255.255.255,用于主机自我测试,通常使用127.0.0.1。
- 广播地址(Broadcast Address):用于将信息发送到网络上的所有设备。例如,192.168.1.255。
- 私有地址(Private Address):用于局域网(LAN)内部通信,不可在互联网上使用。包括以下范围:
- A类:10.0.0.0 到 10.255.255.255
- B类:172.16.0.0 到 172.31.255.255
- C类:192.168.0.0 到 192.168.255.255
IPv6地址是128位长的二进制数,通常表示为八组十六进制数之间用冒号分隔(例如,2001:0db8:85a3:0000:0000:8a2e:0370:7334)。IPv6地址类型主要有以下几种:
- 单播地址(Unicast Address):标识单一接口的地址。
- 全球单播地址(Global Unicast Address):类似于IPv4的公有地址。
- 链路本地地址(Link-Local Address):仅在单一链路上有效,前缀为fe80::/10。
- 站点本地地址(Site-Local Address):类似于IPv4的私有地址,但已被弃用,前缀为fec0::/10。
- 多播地址(Multicast Address):用于一对多通信,前缀为ff00::/8。
- 任播地址(Anycast Address):分配给多个接口,但数据包仅发送到距离最近的接口
7.3 域名和 IP 的关系?一个 IP 可以对应多个域名吗?一个域名可以对应多个IP吗?
- 域名(Domain Name):人类可读的地址,用于标识和访问网站及其他网络资源(例如,
www.example.com
)。 - IP地址(Internet Protocol Address):计算机可读的地址,用于标识网络中的设备(例如,
192.168.1.1
)。
域名和IP地址之间是通过DNS(Domain Name System)来进行映射和解析的。
一个域名可以对应多个 IP,但这种情况 DNS 做负载均衡的,在用户访问过程中,一个域名只能对应一个 IP。
而一个IP却可以对应多个域名,是一对多的关系。
7.4 IPV4 地址不够如何解决?
- DHCP:动态主机配置协议,动态分配 IP 地址,只给接入网络的设备分配 IP 地址,因此同一个 MAC 地址的设备,每次接入互联网时,得到的 IP 地址不一定是相同的,该协议使得空闲的 IP 地址可以得到充分利用。
- CIDR:无类别域间路由。CIDR 消除了传统的 A 类、B 类、C 类地址以及划分子网的概念,因而更加有效地分配 IPv4 的地址空间,但无法从根本上解决地址耗尽的问题。
- NAT:网络地址转换协议,我们知道属于不同局域网的主机可以使用相同的 IP 地址,从而一定程度上缓解了 IP 资源枯竭的问题,然而主机在局域网中使用的 IP 地址是不能在公网中使用的,当局域网主机想要与公网主机进行通信时,NAT 方法可以将该主机 IP 地址转换为全球 IP 地址。该协议能够有效解决 IP 地址不足的问题。
- IPv6:作为接替 IPv4 的下一代互联网协议,其可以实现 2 的 128 次方个地址,而这个数量级,即使给地球上每一粒沙子都分配一个 IP 地址也够用,该协议能够从根本上解决 IPv4 地址不够用的问题。
7.5 说下 ARP 协议的工作过程?
ARP(Address Resolution Protocol,地址解析协议)是用于将IP地址解析为对应物理网络地址(如MAC地址)的协议,主要在IPv4网络中使用。它在局域网(LAN)中起到了关键作用,使设备能够通过IP地址找到对应的硬件地址,从而实现数据帧在局域网中的正确传输。
- ARP请求:当主机 A 要发送数据给主机 B 时,首先会在自己的 ARP 缓存中查找主机 B 的 MAC 地址。如果没有找到,主机 A 会向网络中广播一个 ARP 请求数据包,请求网络中的所有主机告诉它们的 MAC 地址;这个请求包含了请求设备和目标设备的 IP 和 MAC 地址。
- ARP应答:网络中的所有主机都会收到这个 ARP 请求,但只有主机 B 会回复 ARP 应答,告诉主机 A 自己的 MAC 地址。并且主机 B 会将主机 A 的 IP 和 MAC 地址映射关系缓存到自己的 ARP 缓存中,以便下次通信时直接使用。
- 数据传输:在获得主机B的MAC地址后,主机A(也会将主机 B 的 IP 和 MAC 地址映射关系缓存到自己的 ARP 缓存中)就可以将目标MAC地址设置为主机B的MAC地址,从而正确地构建以太网帧并发送到局域网中,这些数据帧会通过交换机或集线器等网络设备正确地传送到主机B。
7.6 为什么既有 IP 地址,又有 MAC 地址?
MAC 地址和 IP 地址都有什么作用?
- MAC 地址是数据链路层和物理层使用的地址,是写在网卡上的物理地址,用来定义网络设备的位置,不可变更。
- IP 地址是网络层和以上各层使用的地址,是一种逻辑地址。IP 地址用来区别网络上的计算机。
为什么有了 MAC 地址还需要 IP 地址?
如果我们只使用 MAC 地址进行寻址的话,我们需要路由器记住每个 MAC 地址属于哪个子网,不然一次路由器收到数据包都要满世界寻找目的 MAC 地址。而我们知道 MAC 地址的长度为 48 位,也就是最多共有 2 的 48 次方个 MAC 地址,这就意味着每个路由器需要 256T 的内存,显然是不现实的。
和 MAC 地址不同,IP 地址是和地域相关的,在一个子网中的设备,我们给其分配的 IP 地址前缀都是一样的,这样路由器就能根据 IP 地址的前缀知道这个设备属于哪个子网,剩下的寻址就交给子网内部实现,从而大大减少了路由器所需要的内存。
为什么有了 IP 地址还需要 MAC 地址?
- 只有当设备连入网络时,才能根据他进入了哪个子网来为其分配 IP 地址,在设备还没有 IP 地址的时候,或者在分配 IP 的过程中。我们需要 MAC 地址来区分不同的设备。
- IP 地址可以比作为地址,MAC 地址为收件人,在一次通信过程中,两者是缺一不可的。
7.7 ICMP 协议的功能?
ICMP(Internet Control Message Protocol,网际控制报文协议) 是用于在IP网络中传递控制和错误信息的协议。它是在网络层(OSI模型的第三层)之上运行的协议,主要用于在IP网络中进行诊断、错误报告和控制消息的传递。ICMP协议的功能包括但不限于以下几点:
- 错误报告:ICMP用于向发送者报告网络层发生的错误,例如目标不可达、超时、路由器发生故障等。
- 路由器发现:ICMP可用于路由器的发现和配置,例如路由器通告消息(Router Advertisement)和路由器请求消息(Router Solicitation)。
- Ping测试:ICMP的Echo请求和Echo应答消息被用于Ping测试,以测试主机之间的连通性和延迟。
- TTL过期:ICMP的TTL(Time to Live)过期消息用于报告数据包在网络中被丢弃的情况,通常由于数据包在转发过程中超过了其TTL值。
- 片段超时:ICMP的片段超时消息用于报告IP数据报在传输过程中被丢弃的情况,通常由于数据包片段未能在超时时间内到达目的地而被丢弃。
- 重定向:ICMP的重定向消息用于告知发送者修改其路由表以改进数据包的转发效率。
- MTU探测:ICMP的路径MTU探测(Path MTU Discovery)用于发现通向目标主机的最大传输单元(MTU)以避免分片。
- 多播/任播测试:ICMP用于进行多播和任播地址的测试和诊断。
比如我们日常使用得比较多的 ping,就是基于 ICMP 的。
在 IP
通信中如果某个 IP
包因为某种原因未能达到目标地址,那么这个具体的原因将由 ICMP 负责通知。
ICMP 报文是封装在 IP 包里面,它工作在网络层,是 IP 协议的助手。
7.8 ping的工作原理
ping,Packet Internet Groper,一个网络工具,主要用来测试网络连接的可达性和延迟。
ping 的过程主要基于 ICMP(Internet Control Message Protocol,互联网控制消息协议)实现,其基本过程包括:
- 当执行 Ping 命令,如
ping www.google.com
,Ping 首先解析域名获取 IP 地址,然后向目标 IP 发送一个 ICMP Echo Request 消息。 - 当目标 IP 收到 ICMP Echo Request 消息后,它会生成一个 ICMP Echo Reply 消息并返回,即 Ping 响应消息。
- 发起 Ping 命令的设备接收到 ICMP Echo Reply 消息后,计算并显示从发送 Echo Request 到接收到 Echo Reply 的时间(通常称为往返时间 RTT,Round-Trip Time),以及可能的丢包情况。
Ping 通常会发送多个请求,以便提供平均响应时间和丢包率等信息,以便我们了解网络连接的质量。
7.9 断网了,还能ping通127.0.0.1吗?
通常情况下,即使网络连接断开,也可以通过回环接口(Loopback Interface)ping通本地主机的回环地址127.0.0.1。回环地址是本地主机自身的虚拟网络接口,用于在本地主机内部进行通信,不经过物理网络设备,因此即使网络断开也可以正常工作。
回环接口是网络协议栈中的一个虚拟接口,用于模拟数据在网络中的传输。当数据发送到回环地址时,操作系统会将数据直接传输给回环接口,然后再从回环接口发送到目标地址,实现了数据的回环传输。
7.10 和 localhost 以及 0.0.0.0 有区别吗
- 127.0.0.1:127.0.0.1是回环地址(Loopback Address),通常用于本地主机内部进行通信。当数据发送到127.0.0.1时,操作系统会将数据传输给回环接口,然后再从回环接口发送到目标地址,实现了数据的回环传输。127.0.0.1始终指向本地主机自身,不会通过网络传输,用于测试本地主机的网络协议栈是否正常工作以及网络服务是否可用。
- localhost:localhost是一个主机名(Hostname),通常映射到回环地址127.0.0.1。当在计算机上使用localhost时,实际上是在使用回环地址127.0.0.1,用于访问本地主机上的网络服务。localhost是一个常见的网络标识符,用于指代本地主机。
- 0.0.0.0:0.0.0.0是一个特殊的IP地址,通常用于表示任意主机或任意地址。当服务器配置为监听0.0.0.0时,表示它将接受来自任何IP地址的连接,可以用于在所有可用网络接口上监听服务。在某些情况下,0.0.0.0也用于指示目标地址未指定或未知。
8 网络安全
8.1 说说有哪些安全攻击?
络安全攻击主要分为两种类型,被动攻击和主动攻击
- 被动攻击:是指攻击者从网络上窃听他人的通信内容,通常把这类攻击称为截获,被动攻击主要有两种形式:消息内容泄露攻击和流量分析攻击。由于攻击者没有修改数据,使得这种攻击很难被检测到。
- 主动攻击:直接对现有的数据和服务造成影响,常见的主动攻击类型有:
- 篡改:攻击者故意篡改网络上送的报文,甚至把完全伪造的报文传送给接收方。
- 恶意程序:恶意程序种类繁多,包括计算机病毒、计算机蠕虫、特洛伊木马、后门入侵、流氓软件等等。
- 拒绝服务 Dos:攻击者向服务器不停地发送分组,使服务器无法提供正常服务。
8.2 DNS 劫持了解吗?
DNS劫持是一种网络攻击,通过篡改DNS(Domain Name System)解析结果来劫持用户的网络流量。DNS劫持攻击者会修改DNS解析请求或响应,将用户重定向到恶意网站或者欺骗页面。
DNS劫持可以通过多种方式实现,其中包括:
- 本地DNS劫持:攻击者在受害者计算机或网络中植入恶意软件,使其修改本地主机的DNS设置,将合法的DNS服务器替换为攻击者控制的恶意DNS服务器。
- 路由器DNS劫持:攻击者入侵路由器或者通过社会工程手段获取路由器管理权限,然后修改路由器的DNS设置,使其指向恶意DNS服务器。
- ISP级别的DNS劫持:攻击者控制了受害者所使用的ISP(Internet Service Provider,互联网服务提供商)的DNS服务器,通过篡改ISP的DNS解析结果来实现DNS劫持。
- 中间人攻击:攻击者通过中间人攻击拦截DNS请求或响应,然后篡改其中的域名解析结果,将用户重定向到恶意网站或者欺骗页面。
怎么应对 DNS 劫持?
- 直接通过 IP 地址访问网站,避开 DNS 劫持
- 由于域名劫持往往只能在特定的网络范围内进行,因此一些高级用户可以通过网络设置让 DNS 指向正常的域名服务器以实现对目标网址的正常访问,例如计算机首选 DNS 服务器的地址固定为 8.8.8.8。
8.3 什么是 CSRF 攻击?如何避免?
CSRF(Cross-Site Request Forgery,跨站请求伪造)攻击是一种网络安全攻击,利用用户在已认证的Web应用程序上的身份验证信息执行未经授权的操作。攻击者通过诱使受害者在访问包含恶意代码的网页时,触发向目标网站发送请求的行为,从而在用户不知情的情况下执行攻击者预先设定的操作,如转账、更改密码等。
CSRF攻击通常包含以下步骤:
- 攻击者准备好一个包含恶意请求的页面,例如一个钓鱼网站或者注入了恶意代码的广告。
- 受害者在已经登录的情况下访问了包含恶意请求的页面。
- 受害者的浏览器自动发送了被伪造的请求到目标网站,由于受害者已经在目标网站登录,因此请求被认为是合法的,从而执行了攻击者的操作。
要防止CSRF攻击,可以采取以下措施:
- 使用CSRF Token:在Web应用程序中引入CSRF Token,确保每个请求都包含一个随机生成的Token,并在服务端验证Token的有效性。攻击者无法获取到有效的CSRF Token,因此无法伪造有效的请求。
- 检查Referer头:Web应用程序可以检查请求的Referer头,确保请求来自合法的来源。但需要注意的是,Referer头可能会被篡改或者缺失,因此不能单独依赖Referer头来防止CSRF攻击。
- 限制敏感操作:对于涉及到敏感操作的请求,应该要求用户输入额外的身份验证信息,例如密码、验证码等,以增加攻击者执行CSRF攻击的难度。
- 使用SameSite属性:在设置Cookie时,可以使用SameSite属性来限制Cookie的发送,防止第三方网站携带Cookie发送CSRF攻击。可以将Cookie设置为SameSite=Strict或者SameSite=Lax,以限制Cookie仅在同源请求中发送。
- 定期审查和更新代码:定期审查和更新Web应用程序的代码,修补已知的安全漏洞,并遵循安全最佳实践,以减少CSRF攻击的风险。
- 添加校验 token:以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
8.4 什么是 DoS、DDoS、DRDoS 攻击?
DoS(Denial of Service,拒绝服务)攻击、DDoS(Distributed Denial of Service,分布式拒绝服务)攻击和DRDoS(Distributed Reflection Denial of Service,分布式反射拒绝服务)攻击都是针对网络服务的攻击手法,旨在使目标系统无法正常提供服务,从而导致服务不可用或严重受损。
- DoS 攻击:DoS攻击是由单个攻击者发起的攻击,通过向目标系统发送大量的请求或者恶意数据包,耗尽目标系统的资源(如带宽、处理能力、存储空间等),从而使正常用户无法访问或使用目标系统的服务。DoS攻击可以采用多种手段实现,包括网络层攻击(如SYN Flood、UDP Flood)、应用层攻击(如HTTP Flood、Slowloris攻击)等。
- DDoS 攻击:DDoS攻击是由多个攻击者协同发起的攻击,通过分布在全球各地的大量“僵尸”计算机(也称为“肉鸡”或“僵尸网络”)向目标系统发送大量的请求或者恶意数据包,造成目标系统过载,从而使其无法正常提供服务。DDoS攻击通常规模更大、更难以应对,因为攻击流量来自于多个来源,并且攻击者可以很容易地控制和伪装攻击流量的来源。
- DRDoS 攻击:DRDoS攻击是一种利用第三方系统的资源反射攻击目标系统的攻击方式。攻击者向第三方系统发送请求,伪装成目标系统的IP地址,并请求返回大量的响应数据,这些响应数据会发送到目标系统,造成目标系统的过载。DRDoS攻击利用了第三方系统的反射响应特性,使攻击者能够轻易地放大攻击流量,并且很难追溯到攻击者的真实身份。
如何防范 DDoS?
针对 DDoS 中的流量攻击,最直接的方法是增加带宽,理论上只要带宽大于攻击流量就可以了,但是这种方法成本非常高。在有充足带宽的前提下,我们应该尽量提升路由器、网卡、交换机等硬件设施的配置。
针对资源耗尽攻击,我们可以升级主机服务器硬件,在网络带宽得到保证的前提下,使得服务器能够有效对抗海量的 SYN 攻击包。我们也可以安装专业的抗 DDoS 防火墙,从而对抗 SYN Flood 等流量型攻击。瓷碗,负载均衡,CDN 等技术都能有效对抗 DDos 攻击。
8.5 什么是 XSS 攻击,如何避免?
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全攻击,攻击者通过在受害者的浏览器中注入恶意脚本,来执行恶意操作。这些脚本通常以HTML、JavaScript等形式存在,可以窃取用户的会话信息、篡改网页内容、重定向用户到恶意网站等。XSS攻击通常分为以下几种类型:
- 存储型 XSS:攻击者将恶意脚本存储到目标网站的数据库中,当用户访问包含恶意脚本的页面时,脚本会从服务器端加载并执行。
- 反射型 XSS:攻击者将恶意脚本作为参数或者URL的一部分,发送给目标用户,当用户点击恶意链接时,脚本会在用户的浏览器中执行。
- DOM-based XSS:攻击者利用客户端的DOM环境,通过修改页面的DOM结构来执行恶意脚本。
如何应对 XSS 攻击?
- 对输入进行过滤,过滤标签等,只允许合法值。
- HTML 转义
- 对于链接跳转,如
<a href="xxx"
等,要校验内容,禁止以 script 开头的非法链接。 - 限制输入长度
- 将Cookie设置为HttpOnly标志,可以防止JavaScript访问Cookie,从而减少XSS攻击的风险。
8.6 对称加密与非对称加密有什么区别?
对称加密和非对称加密是两种常见的加密算法,它们之间有几个关键区别:
- 密钥数量:
- 对称加密使用相同的密钥来加密和解密数据,因此只需要一个密钥。发送方使用该密钥将数据加密,接收方使用相同的密钥将数据解密。
- 非对称加密使用一对密钥:公钥和私钥。公钥用于加密数据,私钥用于解密数据。因此,发送方使用接收方的公钥来加密数据,接收方使用自己的私钥来解密数据。
- 密钥分发:
- 对称加密需要确保加密和解密双方都安全地共享相同的密钥。这意味着必须在通信双方之间建立一个安全的渠道来传输密钥,否则密钥可能会被窃取或篡改。
- 非对称加密不需要在通信双方之间共享密钥。接收方将自己的公钥公开发布,发送方使用该公钥加密数据,接收方使用自己的私钥解密数据。因此,不需要建立安全的通道来传输密钥。
- 性能:
- 对称加密通常比非对称加密更快速,因为它使用的密钥较少,加密和解密过程更简单。
- 非对称加密通常比对称加密更慢,因为它使用更复杂的数学运算来加密和解密数据。
- 适用场景:
- 对称加密通常用于加密大量数据,如传输文件或通信内容。
- 非对称加密通常用于加密小块数据,如数字签名、SSL/TLS握手过程等。
相关内容
- 数据结构与算法 面试题目总结
- Go 语言优秀资源整理,为项目落地加速🏃
- C/C++ 面试题目总结
- 【MIT 6.5840(6.824)学习笔记】GFS
- 【MIT 6.5840(6.824)学习笔记】 测试分布式系统的线性一致性