计算机网络面试题
本文《计算机网络面试题》由小宇宙从原站整理搬运,详细讲解相关技术要点。
大家好,我是小宇宙。 计算机网络是面试里的经典话题,无论你面的是什么方向,多多少少都会被问到。而且这块的题目有个特点:表面看起来很简单,一问深了就容易卡壳。比如"TCP 三次握手",大家都知道个大概,但要说清楚为什么不是两次、第三次握手丢失会怎样、半连接队列是什么,能流利答下来的人并不多。 这篇文章把计算机网络面试中最常被问到的问题都整理进来了,从网络模型、HTTP/HTTPS、DNS,到 TCP 的握手挥手、拥塞控制,再到实际的网络排查场景和常见的网络攻击,整体覆盖还算全面。内容上尽量把原理讲清楚,而不只是给个答案让你背。 有几块内容是面试里的高频重点,值得多花时间: TCP 三次握手和四次挥手 :不只要知道过程,还要能解释为什么是三次而不是两次、每次丢包会发生什么、TIME\ WAIT 状态是怎么来的,这些追问几乎每次都会出现。 HTTP 和 HTTPS :两者的区别、TLS 握手的四个步骤、为什么 HTTPS 能防中间人攻击,这是应用层最高频的考点。 TCP 可靠传输和拥塞控制 :慢启动、拥塞避免、快重传、快恢复这四个阶段,要能说清楚流程和状态转变。 网络排查场景 :比如"页面加载慢怎么排查""ping 不通但 HTTP 能访问是什么原因",这类实际场景题越来越常见,考的是你对网络协议的整体理解。 如果你是第一次系统复习网络,建议先把 TCP 这块啃透,它在面试里的比重最大,也是最容易拉开差距的地方。 网络模型 网络OSI模型和TCP/IP模型分别介绍一下 OSI七层模型 为了使得多种设备能通过网络相互通信,和为了解决各种不同设备在网络互联中的兼容性问题,国际标准化组织制定了开放式系统互联通信参考模型( Open System Interconnection Reference Model ),也就是 OSI 网络模型,该模型主要有 7 层,分别是应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层。 每一层负责的职能都不同,如下: 应用层,负责给应用程序提供统一的接口; 表示层,负责把数据转换成兼容另一个系统能识别的格式; 会话层,负责建立、管理和终止表示层实体之间的通信会话; 传输层,负责端到端的数据传输; 网络层,负责数据的路由、转发、分片; 数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址; 物理层,负责在物理介质上传输比特流(bit stream)。 由于 OSI 模型实在太复杂,提出的也只是概念理论上的分层,并没有提供具体的实现方案。 事实上,我们比较常见,也比较实用的是四层模型,即 TCP/IP 网络模型,Linux 系统正是按照这套网络模型来实现网络协议栈的。 TCP/IP模型 TCP/IP 协议被组织成四个概念层,其中有三层对应于 ISO 参考模型中的相应层。TCP/IP 协议族并不包含物理层和数据链路层,因此它不能独立完成整个计算机网络系统的功能,必须与许多其他的协议协同工作。TCP/IP 网络通常由上到下分成 4 层,分别是 应用层、传输层、网络层和网络接口层 。 应用层 支持 HTTP、SMTP 等最终用户进程 传输层 处理主机到主机的通信(TCP、UDP) 网络层 寻址和路由数据包(IP 协议) 链路层 通过网络的物理电线、电缆或无线信道移动比特 tcp、ip分别位于哪一层? tcp 在传输层 ip 在网络层 应用层 应用层有哪些协议? HTTP、HTTPS、CDN、DNS、FTP 都是应用层协议 HTTP报文有哪些部分? 分请求报文和响应报文来说明。 请求报文: 请求行:包含请求方法、请求目标(URL或URI)和HTTP协议版本。 请求头部:包含关于请求的附加信息,如Host、User Agent、Content Type等。 空行:请求头部和请求体之间用空行分隔。 请求体:可选,包含请求的数据,通常用于POST请求等需要传输数据的情况。 响应报文: 状态行:包含HTTP协议版本、状态码和状态信息。 响应头部:包含关于响应的附加信息,如Content Type、Content Length等。 空行:响应头部和响应体之间用空行分隔。 响应体:包含响应的数据,通常是服务器返回的HTML、JSON等内容。 HTTP常用的状态码? HTTP 状态码分为 5 大类 1xx 类状态码属于 提示信息 ,是协议处理中的一种中间状态,实际用到的比较少。 2xx 类状态码表示服务器 成功 处理了客户端的请求,也是我们最愿意看到的状态。 3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是 重定向 。 4xx 类状态码表示客户端发送的 报文有误 ,服务器无法处理,也就是错误码的含义。 5xx 类状态码表示客户端请求报文正确,但是 服务器处理时内部发生了错误 ,属于服务器端的错误码。 其中常见的具体状态码有: 200:请求成功; 301:永久重定向;302:临时重定向; 404:无法找到此页面;405:请求的方法类型不支持; 500:服务器内部出错。 HTTP返回状态301 302分别是什么? 3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是 重定向 。 「 301 Moved Permanently 」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。 「 302 Found 」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。 301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。 http 502和 504 的区别? 502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。 504 Gateway Time out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器收到响应。 举一个例子,假设 nginx 是代理服务器,收到客户端的请求后,将请求转发到后端服务器(tomcat 等)。 当nginx收到了无效的响应时,就返回502。 当nginx超过自己配置的超时时间,还没有收到请求时,就返回504错误。 HTTP层请求的类型有哪些? GET:用于请求获取指定资源,通常用于获取数据。 POST:用于向服务器提交数据,通常用于提交表单数据或进行资源的创建。 PUT:用于向服务器更新指定资源,通常用于更新已存在的资源。 DELETE:用于请求服务器删除指定资源。 HEAD:类似于GET请求,但只返回资源的头部信息,用于获取资源的元数据而不获取实际内容。 GET和POST的使用场景,有哪些区别? 根据 RFC 规范, GET 的语义是从服务器获取指定的资源 ,这个资源可以是静态的文本、页面、图片视频等。GET 请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII,所以 GET 请求的参数只允许 ASCII 字符 ,而且浏览器会对 URL 的长度有限制(HTTP协议本身对 URL长度并没有做任何规定)。 比如,你打开我的文章,浏览器就会发送 GET 请求给服务器,服务器就会返回文章的所有文字及资源。 根据 RFC 规范, POST 的语义是根据请求负荷(报文body)对指定的资源做出处理 ,具体的处理方式视资源类型而不同。POST 请求携带数据的位置一般是写在报文 body 中,body 中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对 body 大小做限制。 比如,你在我文章底部,敲入了留言后点击「提交」( 暗示你们留言 ),浏览器就会执行一次 POST 请求,把你的留言文字放进了报文 body 里,然后拼接好 POST 请求头,通过 TCP 协议发送给服务器。 如果从 RFC 规范定义的语义来看: GET 方法就是安全且幂等的 ,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以, 可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签 。 POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是 不安全 的,且多次提交数据就会创建多个资源,所以 不是幂等 的。所以, 浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签 。 但是实际过程中,开发者不一定会按照 RFC 规范定义的语义来实现 GET 和 POST 方法。比如: 可以用 GET 方法实现新增或删除数据的请求,这样实现的 GET 方法自然就不是安全和幂等。 可以用 POST 方法实现查询数据的请求,这样实现的 POST 方法自然就是安全和幂等。 HTTP的长连接是什么? HTTP 协议采用的是「请求 应答」的模式,也就是客户端发起了请求,服务端才会返回响应,一来一回这样子。 由于 HTTP 是基于 TCP 传输协议实现的,客户端与服务端要进行 HTTP 通信前,需要先建立 TCP 连接,然后客户端发送 HTTP 请求,服务端收到后就返回响应,至此「请求 应答」的模式就完成了,随后就会释放 TCP 连接。 如果每次请求都要经历这样的过程:建立 TCP 请求资源 响应资源 释放连接,那么此方式就是 HTTP 短连接 ,如下图: 这样实在太累人了,一次连接只能请求一次资源。 能不能在第一个 HTTP 请求完后,先不断开 TCP 连接,让后续的 HTTP 请求继续使用此连接? 当然可以,HTTP 的 Keep Alive 就是实现了这个功能,可以使用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,避免了连接建立和释放的开销,这个方法称为 HTTP 长连接 。 HTTP 长连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。 HTTP默认的端口是什么? http 是 80,https 默认是 443。 HTTP1.1怎么对请求做拆包,具体来说怎么拆的? 在HTTP/1.1中,请求的拆包是通过"Content Length"头字段来进行的。该字段指示了请求正文的长度,服务器可以根据该长度来正确接收和解析请求。 具体来说,当客户端发送一个HTTP请求时,会在请求头中添加"Content Length"字段,该字段的值表示请求正文的字节数。 服务器在接收到请求后,会根据"Content Length"字段的值来确定请求的长度,并从请求中读取相应数量的字节,直到读取完整个请求内容。 这种基于"Content Length"字段的拆包机制可以确保服务器正确接收到完整的请求,避免了请求的丢失或截断问题。 http 断点重传是什么? 断点续传是HTTP/1.1协议支持的特性。实现断点续传的功能,需要客户端记录下当前的下载进度,并在需要续传的时候通知服务端本次需要下载的内容片段。 一个最简单的断点续传流程如下: 1. 客户端开始下载一个1024K的文件,服务端发送Accept Ranges: bytes来告诉客户端,其支持带Range的请求 2. 假如客户端下载了其中512K时候网络突然断开了,过了一会网络可以了,客户端再下载时候,需要在HTTP头中申明本次需要续传的片段:Range:bytes=512000 这个头通知服务端从文件的512K位置开始传输文件,直到文件内容结束 3. 服务端收到断点续传请求,从文件的512K位置开始传输,并且在HTTP头中增加:Content Range:bytes 512000 /1024000,Content Length: 512000。并且此时服务端返回的HTTP状态码应该是206 Partial Content。如果客户端传递过来的Range超过资源的大小,则响应416 Requested Range Not Satisfiable 通过上面流程可以看出:断点续传中4个HTTP头不可少的, 分别是Range头、Content Range头、Accept Ranges头、Content Length头 。其中第一个Range头是客户端发过来的,后面3个头需要服务端发送给客户端。下面是它们的说明: Accept Ranges: bytes :这个值声明了可被接受的每一个范围请求, 大多数情况下是字节数 bytes Range: bytes=开始位置 结束位置 :Range是浏览器告知服务器所需分部分内容范围的消息头。 HTTP为什么不安全? HTTP 由于是明文传输,所以安全上存在以下三个风险: 窃听风险 ,比如通信链路上可以获取通信内容,用户号容易没。 篡改风险 ,比如强制植入垃圾广告,视觉污染,用户眼容易瞎。 冒充风险 ,比如冒充淘宝网站,用户钱容易没。 HTTP S 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议,可以很好的解决了上述的风险: 信息加密 :交互信息无法被窃取,但你的号会因为「自身忘记」账号而没。 校验机制 :无法篡改通信内容,篡改了就不能正常显示,但百度「竞价排名」依然可以搜索垃圾广告。 身份证书 :证明淘宝是真的淘宝网,但你的钱还是会因为「剁手」而没。 HTTP和HTTPS 的区别? 区别主要有以下四点: HTTP 是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,使得报文能够加密传输。 HTTP 连接建立相对简单, TCP 三次握手之后便可进行 HTTP 的报文传输。而 HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输。 两者的默认端口不一样,HTTP 默认端口号是 80,HTTPS 默认端口号是 443。 HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。 HTTPS握手过程说一下 注意:以下描述的是 TLS 1.2 基于 RSA 密钥交换的四次握手过程。 TLS 1.3(RFC 8446,2018 年发布)已经正式移除了 RSA 密钥交换 ,只允许 (EC)DHE 这类支持前向安全的算法;同时把握手从 TLS 1.2 的 2 RTT 简化为 1 RTT ,并支持 0 RTT 会话恢复 。现代浏览器和服务端默认已经使用 TLS 1.2/1.3,RSA 密钥交换仅作为历史知识了解即可。 传统的 TLS 1.2 握手基本都是使用 RSA 算法来实现密钥交换的,在将 TLS 证书部署服务端时,证书文件其实就是服务端的公钥,会在 TLS 握手阶段传递给客户端,而服务端的私钥则一直留在服务端,一定要确保私钥不能被窃取。 在 RSA 密钥协商算法中,客户端会生成随机密钥,并使用服务端的公钥加密后再传给服务端。根据非对称加密算法,公钥加密的消息仅能通过私钥解密,这样服务端解密后,双方就得到了相同的密钥,再用它加密应用消息。 我用 Wireshark 工具抓了用 RSA 密钥交换的 TLS 握手过程,你可以从下面看到,一共经历了四次握手: TLS 第一次握手 首先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。在这一步,客户端主要向服务器发送以下信息: (1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。 (2)客户端生成的随机数(Client Random),后面用于生成「会话秘钥」的条件之一。 (3)客户端支持的密码套件列表,如 RSA 加密算法。 TLS 第二次握手 服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容: (1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。 (2)服务器生成的随机数(Server Random),也是后面用于生成「会话秘钥」的条件之一。 (3)确认的密码套件列表,如 RSA 加密算法。 (4)服务器的数字证书。 TLS 第三次握手 客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。 如果证书没有问题,客户端会 从数字证书中取出服务器的公钥 ,然后使用它加密报文,向服务器发送如下信息: (1)一个随机数(pre master key)。该随机数会被服务器公钥加密。 (2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。 (3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有握手内容做一个摘要,用来供服务端校验。 上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。 服务器和客户端有了这三个随机数(Client Random、Server Random、pre master key),接着就用双方协商的加密算法,各自计算出本次通信的「会话秘钥」 。 TLS 第四次握手 服务器收到客户端的第三个随机数(pre master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。 然后,向客户端发送最后的信息: (1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。 (2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有握手内容做一个摘要,用来供客户端校验。 至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。 HTTPS是如何防范中间人的攻击? 主要通过加密和身份校验机制来防范中间人攻击的: 加密:https 握手期间会通过非对称加密的方式来协商出对称加密密钥。 身份校验:服务器会向证书颁发机构申请数字证书,证书中包含了服务器的公钥和其他相关信息。当客户端与服务器建立连接时,服务器会将证书发送给客户端。客户端会验证证书的合法性,包括检查证书的有效期、颁发机构的信任等。如果验证通过,客户端会使用证书中的公钥来加密通信数据,并将加密后的数据发送给服务器,然后由服务端用私钥解密。 中间人攻击的关键在于攻击者冒充服务器与客户端建立连接,并同时与服务器建立连接。 但由于攻击者无法获得服务器的私钥,因此无法正确解密客户端发送的加密数据。同时,客户端会在建立连接时验证服务器的证书,如果证书验证失败或存在问题,客户端会发出警告或中止连接。 Http1.1和2.0的区别是什么? HTTP/2 相比 HTTP/1.1 性能上的改进: 头部压缩 :HTTP/2 会 压缩头 (Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你 消除重复的部分 。这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就 提高速度 了。 二进制格式 :HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了 二进制格式 ,头信息和数据体都是二进制,并且统称为帧(frame): 头信息帧(Headers Frame)和数据帧(Data Frame) 。这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这 增加了数据传输的效率 。 并发传 输:引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。解决了HTTP/1.1 队头阻塞的问题: 服务器主动推送资源 :HTTP/2 引入了 Server Push 机制,服务端可以在客户端还没请求的情况下主动把相关资源推送给它。需要注意的是, Chrome 106(2022 年 10 月)起已默认禁用 HTTP/2 Server Push ——实践中它的采用率不到 2%,性能收益也不稳定;HTTP/3 规范虽然保留了 Push 但几乎没有实现。现在的替代方案是 103 Early Hints(RFC 8297) :服务器先返回 103 响应告诉浏览器哪些资源可以提前加载,再交给浏览器自行决定是否预取。 HTTP进行TCP连接之后,在什么情况下会中断 当服务端或者客户端执行 close 系统调用的时候,会发送FIN报文,就会进行四次挥手的过程 当发送方发送了数据之后,接收方超过一段时间没有响应ACK报文,发送方重传数据达到最大次数的时候,就会断开TCP连接 当HTTP长时间没有进行请求和响应的时候,超过一定的时间,就会释放连接 HTTP、SOCKET和TCP的区别 HTTP是应用层协议,定义了客户端和服务器之间交换的数据格式和规则;Socket是通信的一端,提供了网络通信的接口;TCP是传输层协议,负责在网络中建立可靠的数据传输连接。它们在网络通信中扮演不同的角色和层次。 HTTP是一种用于传输超文本数据的应用层协议,用于在客户端和服务器之间传输和显示Web页面。 Socket是计算机网络中的一种抽象,用于描述通信链路的一端,提供了底层的通信接口,可实现不同计算机之间的数据交换。 TCP是一种面向连接的、可靠的传输层协议,负责在通信的两端之间建立可靠的数据传输连接。 DNS的全称了解么? DNS的全称是Domain Name System(域名系统),它是互联网中用于将域名转换为对应IP地址的分布式数据库系统。DNS扮演着重要的角色,使得人们可以通过易记的域名访问互联网资源,而无需记住复杂的IP地址。 DNS 中的域名都是用 句点 来分隔的,比如 www.server.com,这里的句点代表了不同层次之间的 界限 。 在域名中, 越靠右 的位置表示其层级 越高 。 毕竟域名是外国人发明,所以思维和中国人相反,比如说一个城市地点的时候,外国喜欢从小到大的方式顺序说起(如 XX 街道 XX 区 XX 市 XX 省),而中国则喜欢从大到小的顺序(如 XX 省 XX 市 XX 区 XX 街道)。 实际上域名最后还有一个点,比如 www.server.com.,这个最后的一个点代表根域名。 也就是,. 根域是在最顶层,它的下一层就是 .com 顶级域,再下面是 server.com。 所以域名的层级关系类似一个树状结构: 根 DNS 服务器(.) 顶级域 DNS 服务器(.com) 权威 DNS 服务器(server.com) 根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中。 这样一来,任何 DNS 服务器就都可以找到并访问根域 DNS 服务器了。 因此,客户端只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。 DNS 域名解析的工作流程? 1. 客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。 2. 本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。 3. 根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。” 4. 本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server.com 的 IP 地址吗?” 5. 顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。 6. 本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。 7. 权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。 8. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。 至此,我们完成了 DNS 的解析过程。现在总结一下,整个过程我画成了一个图。 DNS的端口是多少? 默认端口号是53。 改过host文件吗? host 文件的核心作用是把域名和 IP 地址绑在一起。比如你想让电脑访问 “www.xxx.com (opens new window)” 时直接指向某个特定 IP,不用走公共 DNS 解析,改 host 文件就行。 举个实际场景,程序员测试网站时,还没上线的项目只有服务器 IP,就在 host 里写 “192.168.1.100 www.test.com (opens new window)”,这样输入域名就能直接访问测试服,不用记一串难背的 IP。 DNS的底层使用TCP还是UDP? DNS 同时使用 UDP 和 TCP,端口号都是 53 ,两者各有用途,并不是只用 UDP: 标准的 DNS 查询通常使用 UDP :因为查询和响应的报文一般都很小,UDP 无连接、开销低、响应快,特别适合 DNS 这种需要快速响应的场景。 低延迟: UDP 无需建立连接,减少了传输时延。 简单快速: 相比 TCP 没有连接管理和流量控制的开销。 轻量级: UDP 头部只有 8 字节,对于小型请求响应非常轻量。 下面这些场景 DNS 会使用 TCP : 区域传送(Zone Transfer,AXFR/IXFR) :主从 DNS 服务器之间同步区域数据,数据量大且要求完整可靠, 必须使用 TCP 。 UDP 响应被截断时 :传统 DNS 的 UDP 报文上限是 512 字节 ;如果响应超过这个大小,服务端会在响应里设置 TC(Truncated)标志位 ,客户端收到后会自动 回退到 TCP 重新查询 。现代 DNS 通过 EDNS0(RFC 6891) 扩展把 UDP 报文大小协商到 4096 字节,一定程度上减少了 TCP 回退,但仍不能完全避免。 DNSSEC 签名响应 :因为签名会让响应显著变大,更容易触发截断回退到 TCP。 加密的 DNS 传输 :现代还有 DNS over TLS(DoT,853 端口) 、 DNS over HTTPS(DoH,443 端口) 、 DNS over QUIC(DoQ) 等,它们都基于 TCP/QUIC 而非 UDP,目的是防止查询被窃听和篡改。 尽管 UDP 存在丢包和数据包损坏的风险,但在 DNS 的设计中,这些风险是可以被容忍的。DNS 使用了一些机制来提高可靠性,例如查询超时重传、请求重试、缓存等,以确保数据传输的可靠性和正确性。 HTTP到底是不是无状态的? HTTP是无状态的,这意味着每个请求都是独立的,服务器不会在多个请求之间保留关于客户端状态的信息。在每个HTTP请求中,服务器不会记住之前的请求或会话状态,因此每个请求都是相互独立的。 虽然HTTP本身是无状态的,但可以通过一些机制来实现状态保持,其中最常见的方式是使用Cookie和Session来跟踪用户状态。通过在客户端存储会话信息或状态信息,服务器可以识别和跟踪特定用户的状态,以提供一定程度的状态保持功能。 携带Cookie的HTTP请求是有状态还是无状态的?Cookie是HTTP协议簇的一部分,那为什么还说HTTP是无状态的? 携带Cookie的HTTP请求实际上是可以在一定程度上实现状态保持的,因为Cookie是用来在客户端存储会话信息和状态信息的一种机制。当浏览器发送包含Cookie的HTTP请求时,服务器可以通过读取这些Cookie来识别用户、管理会话状态以及保持特定的用户状态。因此,可以说即使HTTP本身是无状态的协议,但通过Cookie的使用可以实现一定程度的状态保持功能。 HTTP被描述为“无状态”的主要原因是每个HTTP请求都是独立的,服务器并不保存关于客户端的状态信息,每个请求都需要提供足够的信息来理解请求的意图。这样的设计使得Web系统更具有规模化和简单性,但也导致了一些挑战,比如需要额外的机制来处理用户状态和会话管理。 虽然Cookie是HTTP协议簇的一部分,但是HTTP协议在设计初衷上仍然保持无状态特性,即每个请求都是相互独立的。使用Cookie只是在无状态协议下的一种补充机制,用于在客户端存储状态信息以实现状态保持。 cookie和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时,因为数据随每个请求发送到服务器,可能会影响网络传输效率,尤其是在Cookie数据较大时。使用Session时,因为数据存储在服务器端,每次请求都需要查询服务器上的Session数据,这可能会增加服务器的负载,特别是在高并发场景下。 token,session,cookie的区别? session存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号sessionId,通常存放于cookie中。服务器收到cookie后解析出sessionId,再去session列表中查找,才能找到相应session,依赖cookie。 cookie类似一个令牌,装有sessionId,存储在客户端,浏览器通常会自动添加。 token也类似一个令牌,无状态,用户信息都被加密到token中,服务器收到token后解密就可知道是哪个用户,需要开发者手动添加。 如果客户端禁用了cookie,session还能用吗? 默认情况下禁用 Cookie 后,Session 是无法正常使用的 ,因为大多数 Web 服务器都是依赖于 Cookie 来传递 Session 的会话 ID 的。 客户端浏览器禁用 Cookie 时,服务器将无法把会话 ID 发送给客户端,客户端也无法在后续请求中携带会话 ID 返回给服务器,从而导致服务器无法识别用户会话。 但是,有几种方法可以绕过这个问题,尽管它们可能会引入额外的复杂性和/或降低用户体验: 1. URL重写 :每当服务器响应需要保持状态的请求时,将Session ID附加到URL中作为参数。例如,原本的链接http://example.com/page变为http://example.com/page;jsessionid=XXXXXX,服务器端需要相应地解析 URL 来获取 Session ID,并维护用户的会话状态。这种方式的缺点是URL变得不那么整洁,且如果用户通过电子邮件或其他方式分享了这样的链接,可能导致Session ID的意外泄露。 2. 隐藏表单字段 :在每个需要Session信息的HTML表单中包含一个隐藏字段,用来存储Session ID。当表单提交时,Session ID随表单数据一起发送回服务器,服务器通过解析表单数据中的 Session ID 来获取用户的会话状态。这种方法仅适用于通过表单提交的交互模式,不适合链接点击或Ajax请求。 如果我把数据存储到 localStorage,和Cookie有什么区别? 存储容量: Cookie 的存储容量通常较小,每个 Cookie 的大小限制在几 KB 左右。而 LocalStorage 的存储容量通常较大,一般限制在几 MB 左右。因此,如果需要存储大量数据,LocalStorage 通常更适合; 数据发送: Cookie 在每次 HTTP 请求中都会自动发送到服务器,这使得 Cookie 适合用于在客户端和服务器之间传递数据。而 localStorage 的数据不会自动发送到服务器,它仅在浏览器端存储数据,因此 LocalStorage 适合用于在同一域名下的不同页面之间共享数据; 生命周期:Cookie 可以设置一个过期时间,使得数据在指定时间后自动过期。而 LocalStorage 的数据将永久存储在浏览器中,除非通过 JavaScript 代码手动删除; 安全性:Cookie 的安全性较低,因为 Cookie 在每次 HTTP 请求中都会自动发送到服务器,存在被窃取或篡改的风险。而 LocalStorage 的数据仅在浏览器端存储,不会自动发送到服务器,相对而言更安全一些; 什么数据应该存在到cookie,什么数据存放到 Localstorage Cookie 适合用于在客户端和服务器之间传递数据、跨域访问和设置过期时间,而 LocalStorage 适合用于在同一域名下的不同页面之间共享数据、存储大量数据和永久存储数据。 JWT 令牌和传统方式有什么区别? 无状态性:JWT是无状态的令牌,不需要在服务器端存储会话信息。相反,JWT令牌中包含了所有必要的信息,如用户身份、权限等。这使得JWT在分布式系统中更加适用,可以方便地进行扩展和跨域访问。 安全性:JWT使用密钥对令牌进行签名,确保令牌的完整性和真实性。只有持有正确密钥的服务器才能对令牌进行验证和解析。这种方式比传统的基于会话和Cookie的验证更加安全,有效防止了CSRF(跨站请求伪造)等攻击。 跨域支持:JWT令牌可以在不同域之间传递,适用于跨域访问的场景。通过在请求的头部或参数中携带JWT令牌,可以实现无需Cookie的跨域身份验证。 JWT 令牌都有哪些字段?( 没答上来,忘了有哪些,没想到会问) JWT令牌由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature)。其中,头部和载荷均为JSON格式,使用Base64编码进行序列化,而签名部分是对头部、载荷和密钥进行签名后的结果。 JWT 令牌为什么能解决集群部署,什么是集群部署?( 答上来了) 在传统的基于会话和Cookie的身份验证方式中,会话信息通常存储在服务器的内存或数据库中。但在集群部署中,不同服务器之间没有共享的会话信息,这会导致用户在不同服务器之间切换时需要重新登录,或者需要引入额外的共享机制(如Redis),增加了复杂性和性能开销。 而JWT令牌通过在令牌中包含所有必要的身份验证和会话信息,使得服务器无需存储会话信息,从而解决了集群部署中的身份验证和会话管理问题。当用户进行登录认证后,服务器将生成一个JWT令牌并返回给客户端。客户端在后续的请求中携带该令牌