计算机网络面试必问
- 作者
- Name
- 青玉白露
- Github
- @white0dew
- Modified on
- Reading time
- 61 分钟
阅读:.. 评论:..
HTTP常用的状态码及其含义
HTTP状态码是用来表示服务器响应客户端请求的状态。常用的状态码分为以下几类:
状态码 | 含义 |
---|---|
200 | OK:请求成功,服务器已返回所请求的数据。 |
201 | Created:请求成功并且服务器创建了新的资源。 |
204 | No Content:服务器成功处理了请求,但没有返回任何内容。 |
301 | Moved Permanently:请求的资源已被永久移动到新的URL。 |
302 | Found:请求的资源临时从不同的URI响应请求。 |
400 | Bad Request:服务器无法理解客户端的请求。 |
401 | Unauthorized:请求要求用户的身份认证。 |
403 | Forbidden:服务器理解请求但拒绝执行。 |
404 | Not Found:服务器找不到请求的资源。 |
500 | Internal Server Error:服务器内部错误,无法完成请求。 |
502 | Bad Gateway:作为网关或代理工作的服务器从上游服务器收到无效响应。 |
503 | Service Unavailable:服务器当前无法处理请求(过载或维护)。 |
HTTP常用的请求方式,区别和用途
HTTP请求方式有多种,常用的有以下几种:
方法 | 描述 | 区别和用途 |
---|---|---|
GET | 请求指定的资源。 | 用于请求数据,不应修改服务器上的任何资源,且参数通过URL传递。 |
POST | 向指定资源提交数据进行处理请求。 | 用于提交数据(如表单数据),会改变服务器上的资源,数据在请求体中。 |
PUT | 向指定资源位置上传其最新内容。 | 用于更新数据,若资源不存在则创建,数据在请求体中。 |
DELETE | 请求服务器删除指定的资源。 | 用于删除服务器上的资源。 |
HEAD | 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头。 | 用于获取报头信息,检查资源的存在性和状态。 |
OPTIONS | 请求查询服务器的性能,或查询与资源相关的选项。 | 用于获取服务器支持的HTTP方法。 |
PATCH | 对资源进行部分修改。 | 用于部分更新资源,与PUT类似,但更适合局部更新。 |
端口及对应的服务
计算机网络中,不同的服务使用不同的端口号来进行通信。常见的端口及其对应服务如下:
端口号 | 服务 | 描述 |
---|---|---|
20/21 | FTP | 文件传输协议,用于文件传输。 |
22 | SSH | 安全外壳协议,用于安全登录和传输。 |
23 | Telnet | 远程登录服务(不安全)。 |
25 | SMTP | 简单邮件传输协议,用于发送电子邮件。 |
53 | DNS | 域名系统,用于域名解析。 |
80 | HTTP | 超文本传输协议,用于网页浏览。 |
110 | POP3 | 邮局协议,用于接收电子邮件。 |
143 | IMAP | 互联网消息访问协议,用于接收电子邮件。 |
443 | HTTPS | 安全的HTTP协议,用于安全的网页浏览。 |
3306 | MySQL | MySQL数据库服务。 |
6379 | Redis | Redis缓存服务。 |
8080 | HTTP Alternate | 常用于HTTP代理和Web服务器的备用端口。 |
计算机网络体系结构
计算机网络体系结构通常采用分层模型,其中最著名的是OSI七层模型和TCP/IP四层模型。记住下面这幅图
我简单说说两种模型的比较和主要内容:
OSI七层模型
- 物理层:传输原始比特流,定义硬件设备标准。
- 数据链路层:提供节点间数据传输,纠错、流控制。
- 网络层:负责数据包路由选择和转发,IP协议。
- 传输层:提供端到端的通信,TCP/UDP协议。
- 会话层:管理会话和数据交换。
- 表示层:数据格式转换,数据加密解密。
- 应用层:提供网络服务和应用接口,HTTP/FTP等协议。
TCP/IP四层模型
- 网络接口层:对应OSI的物理层和数据链路层。
- 网络层:与OSI网络层相当,主要协议是IP。
- 传输层:与OSI传输层相当,主要协议有TCP和UDP。
- 应用层:整合了OSI的应用层、表示层和会话层。
如何理解HTTP协议是无状态的?
「面试官」: 如何理解HTTP协议是无状态的?
「参考回答」:
要理解HTTP协议的无状态特性,我们需要从以下几个方面来分析:
- 无状态的定义HTTP协议的无状态性指的是协议对于事务处理没有记忆能力。每个请求都是独立的,服务器不会在多个请求之间保留任何信息。
- 无状态的表现
- 服务器在处理HTTP请求时,不会记住之前的请求。
- 每次请求都需要客户端提供所有必要的信息。
- 服务器不会主动保存客户端的状态信息。
- 无状态的优缺点
优点:
TODO
缺点:
- 简化了服务器的设计 - 提高了服务器的扩展性 - 减少了服务器资源的占用 - 无法轻易实现需要状态的交互 - 可能增加通信量(每次都要传输全部信息)
- 无状态的应用场景:HTTP的无状态特性非常适合于静态内容的传输,如网页、图片等。
- 如何在无状态协议上实现有状态的交互:尽管HTTP本身是无状态的,但我们可以通过一些技术来模拟有状态的交互:
- 使用Cookies
- 使用Session
- 使用令牌(Token)
为了更直观地理解HTTP的无状态特性,我们可以用一个简单的图表来说明:
这个图表展示了HTTP的无状态特性。即使是同一个客户端连续发送两个请求,服务器也无法识别这两个请求来自同一个客户端。每次请求对服务器来说都是全新的,没有任何上下文。
理解HTTP的无状态特性对于web开发非常重要,它帮助我们设计更加健壮和可扩展的系统,同时也促使我们思考如何在需要状态的场景下合理地使用各种技术来模拟有状态的交互。
你能详细说明一下如何在HTTP这种无状态协议上实现有状态的交互吗
「面试官」:那么,你能详细说明一下如何在HTTP这种无状态协议上实现有状态的交互吗?特别Cookies、Session和Token这三种方式的具体实现和区别。
「参考回答」:
主要有三种常用的方法:Cookies、Session和Token。让我们逐一分析:
- CookiesCookies是存储在客户端(通常是浏览器)的小型文本文件。
- 工作原理:
- 服务器在HTTP响应中设置Set-Cookie头
- 浏览器保存这个Cookie
- 之后的每次请求,浏览器都会在请求头中包含这个Cookie
- 优点:
- 实现简单
- 可以存储用户偏好等非敏感信息
- 缺点:
- 安全性较低,容易被篡改
- 存储容量有限
- 可能被用户禁用
- 工作原理:
- SessionSession是服务器端的机制,用于跟踪用户的状态。
- 工作原理:
- 服务器创建Session并生成唯一的Session ID
- 服务器通过Set-Cookie头将Session ID发送给客户端
- 客户端之后的请求都会包含这个Session ID
- 服务器根据Session ID识别用户并获取相关数据
- 优点:
- 安全性高,敏感数据存储在服务器
- 可存储大量数据
- 缺点:
- 增加服务器负载
- 在分布式系统中实现复杂
- 工作原理:
- TokenToken是一种更现代的方法,特别适用于无状态的RESTful API。
- 工作原理:
- 用户登录后,服务器生成Token
- Token通常包含用户标识、过期时间等信息,并进行加密
- 客户端存储Token(如localStorage)
- 之后的请求中,客户端在Authorization头中携带Token
- 优点:
- 无需在服务器存储会话信息,更易于扩展
- 可以跨域使用
- 安全性高,特别是使用JWT(JSON Web Token)时
- 缺点:
- Token的管理(如过期、刷新)需要额外处理
- 如果存储在localStorage,有XSS攻击的风险
- 工作原理:
为了更直观地理解这三种方法的区别,我们可以用一个图表来对比:
这个图表展示了三种方法在存储位置和状态管理方面的主要区别。
在实际应用中,这些方法often会结合使用。例如,使用Cookie存储Session ID,或者使用Token实现的认证系统配合Session来管理用户状态。选择哪种方法主要取决于应用的具体需求、安全要求以及系统架构。
理解这些方法的原理和区别,对于设计安全、高效的Web应用至关重要。它不仅帮助我们克服HTTP的无状态特性带来的限制,还能让我们更好地处理用户认证、授权等关键问题。
详细说明一下HTTP/1.0、HTTP/1.1和HTTP/2.0的主要区别
「面试官」: 能否详细说明一下HTTP/1.0、HTTP/1.1和HTTP/2.0的主要区别?特别是它们在连接管理、性能优化等方面的改进。
「参考回答」:
HTTP协议的演进主要体现在连接管理、性能优化、安全性等方面。让我们逐个版本分析:
- HTTP/1.0HTTP/1.0是HTTP协议的第一个广泛使用的版本。
- 主要特点:
- 连接管理: 采用短连接模式。每次请求都需要建立一个新的TCP连接,请求完成后立即关闭。
- 请求方法: 支持GET、POST、HEAD等基本方法。
- 缓存机制: 引入了基本的缓存控制机制,如Expires头。
- 局限性:
- 每个请求都需要重新建立连接,效率低下。
- 不支持断点续传。
- 无法复用连接,增加了网络负载。
- 主要特点:
- HTTP/1.1HTTP/1.1是对HTTP/1.0的重大改进,至今仍被广泛使用。
- 主要改进:
- 持久连接: 默认采用长连接(Connection: keep-alive),多个请求可以复用同一个TCP连接。
- 管道机制: 允许在同一个连接中发送多个请求,不需要等待上一个响应返回(但服务器必须按请求顺序返回响应)。
- 断点续传: 支持范围请求,允许传输文件的某个部分。
- 新增请求方法: 增加了PUT、DELETE、OPTIONS等方法。
- 虚拟主机: 引入Host头,允许在同一IP地址上托管多个域名。
- 缓存增强: 引入了更多的缓存控制机制,如ETag。
- 局限性:
- 队头阻塞(Head-of-line blocking)问题: 虽然可以并行发送请求,但服务器必须按顺序返回响应。
- 头部冗余: 每次请求都会携带大量重复的头信息。
- 主要改进:
- HTTP/2.0HTTP/2.0是对HTTP/1.1的重大升级,旨在提高性能和效率。
- 主要改进:
- 多路复用: 在一个TCP连接上可以同时发送多个请求和响应,解决了队头阻塞问题。
- 二进制分帧: 将信息分割为更小的帧,并采用二进制格式编码,提高了传输效率。
- 头部压缩: 使用HPACK算法压缩头部,减少了数据传输量。
- 服务器推送: 服务器可以主动向客户端推送资源,无需客户端请求。
- 请求优先级: 允许客户端设置请求的优先级,进一步优化性能。
- 优势:
- 显著提高了页面加载速度。
- 减少了网络负载。
- 更高效地利用网络资源。
- 主要改进:
为了更直观地理解这三个版本的主要区别,我们可以用一个图表来对比:
你能详细解释一下HTTPS的工作流程吗?
「面试官」: 你能详细解释一下HTTPS的工作流程吗?特别是它如何保证通信的安全性,以及在这个过程中使用了哪些加密技术?
「参考回答」:
HTTPS(Hypertext Transfer Protocol Secure)是HTTP的安全版本,它通过在HTTP和TCP之间添加一个安全层(通常是SSL/TLS)来保证通信的安全性。
HTTPS的工作流程主要包含以下步骤:
- 客户端发起HTTPS请求
- 客户端(通常是浏览器)向服务器的443端口发起请求。
- 服务器发送证书
- 服务器向客户端发送SSL证书,该证书包含了公钥、颁发机构、有效期等信息。
- 客户端验证证书
- 客户端会验证证书的合法性,包括:
- 证书是否过期
- 证书的颁发机构是否可信
- 证书的域名是否匹配
- 客户端会验证证书的合法性,包括:
- 客户端生成随机密钥
- 如果证书验证通过,客户端会生成一个随机的对称加密密钥。
- 使用公钥加密随机密钥
- 客户端使用证书中的公钥对这个随机生成的对称密钥进行加密。
- 发送加密后的随机密钥
- 客户端将加密后的随机密钥发送给服务器。
- 服务器解密随机密钥
- 服务器使用自己的私钥解密,获得客户端发送的随机对称密钥。
- 双方使用对称密钥加密通信
- 此后,客户端和服务器就可以使用这个对称密钥来加密和解密他们之间的通信了。
在这个过程中,HTTPS使用了几种不同的加密技术:
- 非对称加密(公钥加密)
- 用于在不安全的通道上安全地传输对称密钥。
- 常用算法:RSA、ECC(椭圆曲线加密)
- 优点:安全性高
- 缺点:计算速度较慢
- 对称加密
- 用于加密实际的通信内容。
- 常用算法:AES、DES
- 优点:加解密速度快
- 缺点:密钥管理困难
- 散列函数
- 用于生成消息摘要,确保消息完整性。
- 常用算法:SHA-256、MD5(不推荐使用)
- 数字签名
- 结合非对称加密和散列函数,用于身份认证和防止篡改。
HTTPS如何保证通信的安全性:
- 机密性
- 通过对称加密保证通信内容不被窃听。
- 完整性
- 通过消息认证码(MAC)或数字签名确保消息未被篡改。
- 认证
- 通过数字证书确保服务器的身份。
- 防重放
- 使用时间戳或序列号防止重放攻击。
为了更直观地理解HTTPS的工作流程,我们可以用一个图表来说明:
HTTPS的安全性主要依赖于以下几个方面:
- 证书的可靠性:依赖于CA(证书颁发机构)的信誉和安全措施。
- 密钥的安全性:私钥必须妥善保管,不能泄露。
- 加密算法的强度:随着计算能力的提升,需要不断更新使用更强的加密算法。
- 完美前向保密(Perfect Forward Secrecy, PFS):即使长期使用的私钥泄露,之前的通信仍然安全。这通常通过临时的Diffie-Hellman密钥交换来实现。
理解HTTPS的工作原理对于开发安全的Web应用至关重要。它不仅能帮助我们正确配置和使用HTTPS,还能让我们更好地理解潜在的安全威胁和防御措施。例如,了解中间人攻击的原理,我们就能更好地理解为什么证书验证如此重要。
同时,HTTPS虽然大大提高了通信的安全性,但它并不能解决所有的安全问题。例如,它无法防止应用层的漏洞,如SQL注入或跨站脚本攻击(XSS)。因此,在使用HTTPS的同时,我们还需要采取其他的安全措施来全面保护我们的Web应用。
你能详细说明一下GET和POST这两种常用的HTTP请求方法的区别吗?
「面试官」: 接下来,我想了解一下关于HTTP请求方法的问题。你能详细说明一下GET和POST这两种常用的HTTP请求方法的区别吗?特别是在使用场景、安全性、数据传输等方面的差异。
「参考回答」:
GET和POST是HTTP协议中最常用的两种请求方法,它们在使用场景、安全性、数据传输等方面有很大的不同。
让我们从以下几个方面来比较GET和POST:
- 用途和语义
- GET:
- 主要用于获取资源
- 应该是幂等的,即多次请求应该返回相同的结果
- 通常用于读取或查询操作
- POST:
- 主要用于提交数据
- 可以是非幂等的,即可能会改变服务器状态
- 通常用于创建、更新或删除操作
- GET:
- 数据传输
- GET:
- 数据附加在URL之后,作为查询字符串
- 数据长度受限于URL的最大长度(通常为2048字符)
- 数据类型限于ASCII字符
- POST:
- 数据包含在HTTP请求体中
- 数据长度理论上没有限制
- 可以传输任何类型的数据,包括二进制数据
- GET:
- 安全性
- GET:
- 参数暴露在URL中,不适合传输敏感信息
- 参数可能被浏览器历史、服务器日志等记录
- 更容易受到跨站请求伪造(CSRF)攻击
- POST:
- 参数不会显示在URL中,相对更安全
- 参数不会被浏览器缓存或保存在浏览器历史中
- 相对不容易受到CSRF攻击,但仍需要其他安全措施
- GET:
- 缓存
- GET:
- 请求可以被缓存
- 可以被收藏为书签
- 可以被浏览器主动缓存
- POST:
- 请求通常不被缓存
- 不能被收藏为书签
- 不会被浏览器主动缓存
- GET:
- 编码类型
- GET:
- application/x-www-form-urlencoded
- POST:
- application/x-www-form-urlencoded
- multipart/form-data
- application/json
- 等多种类型
- GET:
- 使用场景
- GET:
- 搜索表单
- 静态内容请求
- RESTful API中的读取操作
- POST:
- 登录表单
- 文件上传
- 大量数据传输
- RESTful API中的创建、更新操作
- GET:
为了更直观地理解GET和POST的区别,我们可以用一个对比图表来说明:
理解GET和POST的区别对于Web开发者来说非常重要,它能帮助我们在不同的场景下选择合适的请求方法,并正确处理相关的安全和性能问题。例如:
- 在设计RESTful API时,我们通常使用GET来获取资源,POST来创建资源。
- 对于包含敏感信息的表单,如登录表单,我们应该使用POST方法来提交数据。
- 在处理大量数据或上传文件时,POST是更好的选择。
- 对于需要被搜索引擎索引的页面,使用GET方法更有利于SEO。
- 在实现缓存策略时,我们需要考虑GET请求更容易被缓存的特性。
需要注意的是,虽然POST相对GET来说更安全,但这并不意味着POST就是绝对安全的。在实际应用中,我们还需要采取其他安全措施,如使用HTTPS、实现CSRF保护等,来确保Web应用的整体安全性。
什么是跨域请求,为什么会有跨域限制,以及如何解决跨域问题吗?
「面试官」: 在实际的Web开发中,我们经常需要处理跨域请求的问题。你能详细解释一下什么是跨域请求,为什么会有跨域限制,以及如何解决跨域问题吗?
「参考回答」:
当然,我很乐意详细解释跨域请求的相关问题。跨域请求是Web开发中常见的一个挑战,理解它对于构建现代Web应用至关重要。
- 什么是跨域请求?
跨域请求是指在一个域名的网页中,请求另一个域名的资源。这里的"域"包括:
- 协议(如http, https)
- 域名(如example.com, api.example.com)
- 端口号(如80, 8080)
只要这三者之一不同,就被认为是跨域。例如:
- http://example.com 请求 https://example.com 的资源(协议不同)
- http://example.com 请求 http://api.example.com 的资源(子域名不同)
- http://example.com 请求 http://example.com:8080 的资源(端口不同)
- 为什么会有跨域限制?
跨域限制是浏览器的一种安全机制,称为同源策略(Same-Origin Policy)。它的主要目的是防止恶意网站访问另一个网站的敏感数据。
没有这种限制可能导致的安全问题包括:
- 恶意网站可能会读取用户在其他网站上的私密信息
- 恶意网站可能会执行未经授权的操作,如转账、发送消息等
- 如何解决跨域问题?
有几种常用的方法来解决跨域问题:
a) CORS (Cross-Origin Resource Sharing)
- 这是最常用和推荐的方法
- 服务器通过设置特定的HTTP头来允许跨域请求
- 主要的头部包括:
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
b) JSONP (JSON with Padding)
- 利用
<script>
标签不受同源策略限制的特性 - 只支持GET请求
- 安全性较差,现在使用较少
c) 代理服务器
- 在同源的服务器上设置一个代理
- 浏览器先请求同源服务器,再由服务器转发请求到目标服务器
d) WebSocket
- WebSocket协议不受同源策略的限制
e) postMessage
- HTML5引入的API,用于不同窗口间的通信
- 可以在不同源的文档之间传递消息
为了更直观地理解这些解决方案,我们可以用一个图表来说明:
在实际应用中,CORS是最常用和最推荐的解决方案。以下是一个简单的CORS配置示例(以Node.js和Express为例):
const express = require('express'); const app = express(); app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); next(); }); // 路由定义... app.listen(3000, () => console.log('Server running on port 3000'));
这个例子允许所有域的请求,在生产环境中应该根据实际需求限制允许的域。
理解和正确处理跨域问题对于构建现代Web应用非常重要,特别是在以下场景:
- 前后端分离的架构中,前端和API可能部署在不同的域。
- 使用第三方API时,几乎总是跨域的。
- 在微服务架构中,不同的服务可能部署在不同的域。
同时,在处理跨域问题时,我们还需要注意安全性。
例如,不应该过于宽松地设置CORS策略,应该只允许必要的源、方法和头部。此外,对于敏感操作,仍然需要其他的安全措施,如身份验证和授权。
HTTP 如何实现长连接?在什么时候会超时?
「面试官」:HTTP 如何实现长连接?在什么时候会超时?
「参考回答」:
HTTP 长连接(HTTP Keep-Alive)是 HTTP 协议中的一个重要特性,它允许在单个 TCP 连接上发送多个 HTTP 请求和响应,而不是为每个请求-响应对建立一个新的连接。下面我们来详细讨论 HTTP 长连接的实现和超时情况:
- HTTP 长连接的实现:
- HTTP 长连接的核心特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。
- 在 HTTP/1.1 中,长连接是默认行为。客户端和服务器都可以在 HTTP 头部中使用
Connection: keep-alive
来明确表示希望保持长连接。 - 服务器可以在响应头中设置
Keep-Alive: timeout=<seconds>
来指定连接保持打开的时间。
- HTTP 长连接的超时情况:
- 长连接会在以下情况下超时:
a) 客户端超时:如果客户端在一定时间内没有发送新的请求,可能会主动关闭连接。
b) 服务器超时:服务器通常会设置一个超时时间,如果在这个时间内没有收到新的请求,就会关闭连接。 - 当出现超时时,通常会观察到以下现象:
- 大量的 TIME_WAIT 状态连接:特别是在服务端,如果有大量客户端建立 TCP 连接后长时间没有发送数据,服务端可能会主动关闭这些连接,导致大量连接进入 TIME_WAIT 状态。
- 上图显示了 HTTP 长连接超时的情况。当服务端检测到长时间没有数据交互时,会主动关闭连接,从而产生 TIME_WAIT 状态的连接。
- 长连接会在以下情况下超时:
- 防止超时的策略:
- 设置合理的超时时间:根据应用场景调整服务器的 keep-alive 超时设置。
- 使用心跳机制:在空闲时发送小型的心跳包来保持连接活跃。
- 合理关闭:在应用层面合理地关闭不再需要的连接,而不是依赖超时机制。
什么是数字签名?什么是数字证书?
「面试官」:让我们从数字签名和数字证书开始。什么是数字签名?什么是数字证书?
「参考回答」:
- 数字签名:数字签名是一种电子签名,用于验证数字消息或文档的真实性和完整性。它的工作原理如下:
数字签名的主要作用包括:
- 使用**发送者的私钥**对消息进行加密,生成签名。 - 接收者使用**发送者的公钥**来验证签名的有效性。 - **身份认证**:确保消息确实来自声称的发送者。 - **数据完整性**:确保消息在传输过程中没有被篡改。 - **不可否认性**:发送者无法否认曾发送过该消息。
- 数字证书:数字证书是由可信的第三方(称为证书颁发机构,CA)颁发的电子文档,用于证明某个公钥确实属于声称拥有它的个人或组织。数字证书通常包含以下信息:
数字证书的主要作用是在公钥基础设施(PKI)中建立信任,确保公钥的真实性和可靠性。
- 证书持有者的身份信息 - 证书持有者的公钥 - 证书颁发机构的数字签名 - 证书的有效期 - 证书的序列号
对称加密与非对称加密有什么区别?
「面试官」:你知道对称加密与非对称加密有什么区别?
「参考回答」:对称加密和非对称加密是两种基本的加密方式,主要有以下区别:
- 密钥数量:
- 对称加密:使用同一个密钥进行加密和解密。
- 非对称加密:使用一对密钥(公钥和私钥)。公钥用于加密,私钥用于解密。
- 速度:
- 对称加密:通常更快,适合大量数据的加密。
- 非对称加密:计算复杂度更高,速度较慢。
- 安全性:
- 对称加密:密钥分发是主要的安全隐患。
- 非对称加密:通常被认为更安全,因为私钥不需要共享。
- 用途:
- 对称加密:主要用于大量数据的加密,如文件加密、数据传输等。
- 非对称加密:常用于密钥交换、数字签名等场景。
在实际应用中,常常结合使用这两种加密方式,以平衡安全性和性能。
说说DNS的解析过程?
「面试官」:说说DNS的解析过程?
「参考回答」:好啊,DNS(域名系统)解析是将域名转换为IP地址的过程,基本步骤如下:
- 本地缓存查询:
- 首先,客户端会检查自己的DNS缓存,看是否有所需域名的记录。
- 查询本地DNS服务器:
- 如果本地缓存中没有,客户端会向配置的本地DNS服务器(通常是ISP提供的)发送查询请求。
- 递归查询:
如果本地DNS服务器没有缓存该域名的记录,它会进行递归查询:a) 查询根域名服务器
b) 查询顶级域名服务器(如.com, .org等)
c) 查询权威域名服务器 - 获取IP地址:
- 一旦找到包含所需域名IP地址的权威服务器,该信息会被返回给本地DNS服务器。
- 缓存并返回结果:
- 本地DNS服务器会缓存这个结果,并将IP地址返回给客户端。
- 客户端缓存:
- 客户端收到IP地址后,也会在本地缓存这个结果,以便将来使用。
这个过程可以通过下面的示意图来表示:
这个过程确保了域名系统的分布式和可扩展性,允许全球范围内的域名解析。
什么是CSRF攻击,如何避免?
「面试官」:什么是CSRF攻击,如何避免?
「参考回答」:
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击方式。
- CSRF攻击原理:
- 攻击者诱导用户访问一个恶意网站。
- 该网站会自动向受害者已登录的其他网站发送未经授权的请求。
- 由于请求中包含了用户的身份认证信息(如cookie),服务器会误认为是用户自己发起的合法请求。
- CSRF攻击的特点:
- 利用了用户已认证的身份。
- 欺骗用户的浏览器发送HTTP请求给目标站点。
- 通常用于执行非法的转账、更改密码等操作。
- 避免CSRF攻击的方法:
a) 使用CSRF Token
b) 检查Referer字段
c) 使用SameSite Cookie属性
d) 双重Cookie验证
e) 实施严格的身份验证
f) 使用自定义请求头
示例代码(使用CSRF Token):
// 在服务器端生成CSRF Token String csrfToken = generateRandomToken(); session.setAttribute("csrf_token", csrfToken); // 在HTML表单中包含CSRF Token <form action="/transfer" method="POST"> <input type="hidden" name="csrf_token" value="${csrfToken}"> <!-- 其他表单字段 --> </form> // 在服务器端验证CSRF Token String receivedToken = request.getParameter("csrf_token"); String sessionToken = (String) session.getAttribute("csrf_token"); if (!receivedToken.equals(sessionToken)) { // Token不匹配,拒绝请求 throw new SecurityException("Invalid CSRF Token"); }
通过实施这些安全措施,可以显著降低CSRF攻击的风险。
WebSocket与socket的区别
「面试官」:请说说WebSocket与socket的区别。
「参考回答」:WebSocket和socket虽然名字相似,但它们在本质上有很大的区别,一句话,WebSocket是HTML5新增的协议,用于解决浏览器与服务器全双工通信的问题,而Socket是一个更底层的概念,是网络编程的基础。
- 概念层面:
- Socket:是一个底层的通信接口,是应用层与TCP/IP协议族通信的中间软件抽象层。它是一组接口,在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket后面。
- WebSocket:是一种应用层的协议,它基于TCP协议,实现了浏览器与服务器全双工通信。
- 连接方式:
- Socket:可以支持TCP、UDP等多种传输层协议。
- WebSocket:建立在TCP协议之上,是TCP协议的一种新的应用。
- 使用场景:
- Socket:主要用于服务器端编程,如C/S架构的网络应用。
- WebSocket:主要用于浏览器与服务器全双工通信,适用于网页实时应用。
- 实现方式:
- Socket:需要手动实现通信细节。
- WebSocket:浏览器和服务器都有现成的API,使用更加方便。
- 连接特性:
- Socket:一般需要保持连接,轮询获取数据。
- WebSocket:创建连接后,可以实时双向通信。
- 跨域支持:
- Socket:通常不涉及跨域问题。
- WebSocket:支持跨域通信。
DoS、DDoS、DRDoS攻击的区别
「面试官」:请解释一下什么是DoS、DDoS、DRDoS攻击?
「参考回答」:
这三种攻击都是针对网络服务的可用性进行的攻击,但它们有一些区别:
- DoS (Denial of Service) 攻击:
- 定义:拒绝服务攻击。
- 特点:攻击者使用单一来源向目标发送大量请求。
- 目的:耗尽目标系统的资源(如带宽、CPU、内存等),使其无法正常服务。
- 例子:SYN洪水攻击。
- DDoS (Distributed Denial of Service) 攻击:
- 定义:分布式拒绝服务攻击。
- 特点:攻击者利用多个被控制的计算机(僵尸网络)同时向目标发起攻击。
- 目的:与DoS相同,但规模更大,更难防御。
- 例子:UDP洪水攻击、ICMP洪水攻击。
- DRDoS (Distributed Reflection Denial of Service) 攻击:
- 定义:分布式反射拒绝服务攻击。
- 特点:攻击者伪造受害者的IP地址,向大量服务器发送请求,这些服务器则向受害者回复大量响应。
- 目的:利用反射和放大效应,使攻击更难追踪和防御。
- 例子:NTP反射攻击、DNS放大攻击。
主要区别:
- DoS是单一源攻击,DDoS和DRDoS是分布式攻击。
- DRDoS比DDoS更难追踪,因为真实攻击源被隐藏。
- DRDoS利用合法服务器作为攻击媒介,可能造成更大的影响。
防御这些攻击通常需要结合多种策略,如流量过滤、负载均衡、CDN等。
XSS攻击及其防御
「面试官」:你能解释一下什么是XSS攻击,以及如何避免吗?
「参考回答」:
XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的web安全漏洞,攻击者通过在网页中注入恶意脚本,当用户浏览这些网页时,恶意脚本会在用户的浏览器中执行。
XSS攻击的主要类型:
- 存储型XSS:恶意脚本被存储在数据库中,当用户访问包含此脚本的页面时触发。
- 反射型XSS:恶意脚本包含在URL中,当服务器将此脚本包含在响应中返回时触发。
- DOM型XSS:利用DOM操作在客户端执行恶意脚本。
XSS攻击的危害:
- 窃取用户cookie
- 篡改页面内容
- 钓鱼攻击
- 利用用户权限执行操作
如何避免XSS攻击:
- 输入验证和过滤:
- 对用户输入进行严格验证,过滤特殊字符。
- 使用白名单而不是黑名单进行过滤。
- 输出编码:
- 在输出到HTML、JavaScript、CSS等环境时,对数据进行相应的编码。
- 使用安全的API:
- 优先使用安全的API,如
.textContent
而不是.innerHTML
。
- 优先使用安全的API,如
- 内容安全策略(CSP):
- 实施严格的CSP,限制资源的加载和脚本执行。
- HttpOnly Cookie:
- 为敏感Cookie设置HttpOnly标志,防止JavaScript访问。
- X-XSS-Protection头:
- 启用浏览器内置的XSS防护机制。
- 定期安全审计:
- 对代码进行安全审计,使用自动化工具扫描XSS漏洞。
- 框架和库的安全使用:
- 使用成熟的框架和库,并保持更新到最新的安全版本。
示例代码(Java):
public class XSSFilter { public static String filter(String input) { if (input == null) { return null; } return input.replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll("\"", """) .replaceAll("'", "'") .replaceAll("/", "/"); } }
这个简单的过滤器可以用来转义潜在的危险字符,但在实际应用中,应该使用更完善的安全库。
forward和redirect的区别
「面试官」:请说明一下forward和redirect的区别。
「参考回答」:
Forward(转发)和Redirect(重定向)是Web应用中两种常见的页面跳转方式,它们有以下几个主要区别:
- 请求次数:
- Forward:只有一次HTTP请求。
- Redirect:涉及两次HTTP请求。
- 浏览器URL:
- Forward:浏览器地址栏URL不变。
- Redirect:浏览器地址栏显示新的URL。
- 数据共享:
- Forward:可以共享请求域中的数据。
- Redirect:不能共享请求域中的数据。
- 执行位置:
- Forward:在服务器端完成。
- Redirect:在客户端完成。
- 性能:
- Forward:通常更快,因为只有一次请求。
- Redirect:相对较慢,因为有两次请求。
- 适用场景:
- Forward:适用于内部跳转,如登录成功后跳转到用户主页。
- Redirect:适用于跨域跳转或需要改变URL的场景,如登录后跳转到其他网站。
- WEB-INF访问:
- Forward:可以访问WEB-INF目录下的资源。
- Redirect:不能访问WEB-INF目录下的资源。
- 状态码:
- Forward:不改变HTTP状态码。
- Redirect:返回3xx系列状态码(如302)。
Forward适合内部跳转和数据共享,而Redirect适合需要改变URL或跨域跳转的情况。
ARP协议的工作过程
「面试官」:请说下ARP协议的工作过程。
「参考回答」:
ARP(Address Resolution Protocol,地址解析协议)是一种用于将IP地址转换为物理地址(如MAC地址)的协议。它在局域网中起着至关重要的作用。以下是ARP协议的工作过程:
- ARP请求:
- 当主机A需要与主机B通信时,它首先检查自己的ARP缓存。
- 如果缓存中没有目标IP对应的MAC地址,主机A会发送一个ARP广播请求。
- 这个请求包含了发送方的IP地址和MAC地址,以及目标IP地址。
- ARP响应:
- 局域网内的所有主机都会收到这个广播请求。
- 拥有目标IP地址的主机B会发送一个ARP响应。
- 响应包含主机B的MAC地址。
- 更新ARP缓存:
- 主机A收到响应后,会更新自己的ARP缓存,记录IP地址和对应的MAC地址。
- 这样,下次通信时就可以直接使用缓存中的信息。
- 通信开始:
- 主机A现在知道了主机B的MAC地址,可以开始数据传输。
- 缓存老化:
- ARP缓存项通常有一个生存时间(TTL),过期后会被删除。
- 这确保了缓存中的信息不会过时。
- 免费ARP:
- 主机可能会发送免费ARP(Gratuitous ARP)。
- 这是一种主机主动发布自己IP和MAC对应关系的机制。
- 用于检测IP冲突或更新其他主机的ARP缓存。
ARP协议的工作流程图:
注意:
- ARP是一个不安全的协议,容易受到ARP欺骗攻击。
- 在大型网络中,过多的ARP广播可能会导致网络性能下降。
- 现代网络设备通常有ARP防护机制,如动态ARP检测(DAI)。
IP地址与MAC地址的必要性
「面试官」:有了IP地址,为什么还要用MAC地址?
「参考回答」:
虽然IP地址在网络通信中扮演着重要角色,但MAC地址同样不可或缺。这两种地址在网络通信中各司其职,共同确保数据包能够准确无误地从源主机传输到目标主机。
IP地址的作用:
- IP地址是网络层的地址,用于在互联网范围内进行路由和寻址。
- IP地址可以动态分配,便于网络管理和IP地址资源的有效利用。
- IP地址具有层次结构,便于互联网的分层路由。
MAC地址的必要性:
- MAC地址是数据链路层的地址,用于在同一网段内识别设备。
- MAC地址是全球唯一的,由硬件制造商分配,确保了设备的唯一性。
- MAC地址是固定的,不受网络环境变化影响,提供了稳定的设备标识。
- 在局域网中,数据包的实际传输是基于MAC地址进行的。
- MAC地址用于解决最后一跳问题,即从路由器到最终目标设备的传输。
IP地址和MAC地址的协作:
- 当数据包在互联网上传输时,使用IP地址进行路由。
- 当数据包到达目标网段后,需要通过ARP协议将IP地址解析为MAC地址。
- 最后一跳传输使用MAC地址在局域网内精确定位目标设备。
安全性考虑:
- MAC地址提供了额外的安全层,可用于MAC地址过滤等安全措施。
- 仅依赖IP地址可能导致IP欺骗等安全问题。
总之,IP地址和MAC地址在网络通信中扮演着不同但同样重要的角色。IP地址负责全局寻址和路由,而MAC地址确保了局域网内的精确传输和设备识别。两者的结合使得数据包能够在复杂的网络环境中准确无误地传输。
TCP和UDP对应的常见应用层协议
「面试官」:TCP 和 UDP 分别对应的常见应用层协议有哪些?
「参考回答」:
TCP(传输控制协议)和UDP(用户数据报协议)是传输层的两个主要协议,它们各自支持不同的应用层协议。让我们来看看它们分别对应的常见应用层协议:
TCP对应的常见应用层协议:
HTTP/HTTPS:用于Web浏览,是互联网的基础协议。
FTP:文件传输协议,用于在客户端和服务器之间传输文件。
SMTP:简单邮件传输协议,用于发送电子邮件。
POP3/IMAP:用于接收电子邮件的协议。
Telnet:远程登录协议,允许用户登录到远程计算机。
SSH:安全外壳协议,为远程登录和其他网络服务提供安全通道。
MQTT:消息队列遥测传输,用于物联网(IoT)设备通信。
UDP对应的常见应用层协议:
DNS:域名系统,用于将域名转换为IP地址。
DHCP:动态主机配置协议,用于动态分配IP地址。
SNMP:简单网络管理协议,用于网络设备的监控和管理。
RTP:实时传输协议,用于传输音频和视频数据。
NTP:网络时间协议,用于时间同步。
TFTP:简单文件传输协议,是FTP的简化版本。
SIP:会话发起协议,用于Voice over IP(VoIP)通信。
选择TCP还是UDP的考虑因素:
- 可靠性要求:TCP提供可靠传输,UDP不保证可靠性。
- 速度要求:UDP通常比TCP更快,因为它没有建立连接和错误检查的开销。
- 数据完整性:TCP确保数据完整性,UDP可能丢包。
- 应用特性:实时应用(如视频流)可能更适合UDP,而需要准确传输的应用(如文件传输)更适合TCP。
理解这些协议及其应用场景对于网络编程和系统设计非常重要,能够帮助开发者选择最适合特定应用需求的协议。
URI和URL的区别
「面试官」:请解释一下URI和URL的区别。
「参考回答」:
URI(统一资源标识符)和URL(统一资源定位符)是互联网资源标识和定位的重要概念,它们之间有密切的关系,但也存在一些区别。
URI(Uniform Resource Identifier):
- URI是一个用于标识某一互联网资源名称的字符串。
- 它可以标识各种资源,包括文档、图像、服务等。
- URI是一个抽象的概念,包含两个主要子集:URL和URN。
URL(Uniform Resource Locator):
- URL是URI的一个子集。
- URL不仅标识资源,还提供了定位该资源的方法。
- URL指定了资源的位置和访问它的协议。
主要区别:
范围:
- URI是一个更广泛的概念,包括URL和URN。
- URL是URI的一个特定类型。
功能:
- URI 标识资源。
- URL 定位资源。
组成部分:
- URI可能只包含资源的标识。
- URL通常包含协议、主机名、路径等信息。
示例:
- URI示例:
urn:isbn:0451450523
(一本书的ISBN) - URL示例:
https://www.example.com/page.html
URN(Uniform Resource Name):
- URN是URI的另一个子集,用于在特定命名空间中唯一标识资源。
- URN不提供资源的位置信息。
- 示例:
urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66
在实践中:
- 大多数情况下,我们遇到的都是URL。
- 在Web开发中,URL更为常用,因为它提供了访问资源的具体方法。
图示说明:
理解URI和URL的区别对于Web开发和网络编程非常重要,它有助于正确处理和表示互联网资源。
ICMP协议的功能
「面试官」:请说明ICMP协议的功能。
「参考回答」:
ICMP(Internet Control Message Protocol,互联网控制消息协议)是IP协议族的一个重要成员,主要用于在IP主机、路由器之间传递控制消息。ICMP协议的功能非常广泛,主要包括以下几个方面:
错误报告:
- 目标不可达:当路由器或主机无法将数据包传递到目的地时,会发送ICMP目标不可达消息。
- 超时:如果数据包在传输过程中生存时间(TTL)降为零,会触发ICMP超时消息。
- 参数问题:当IP头部存在问题时,会发送ICMP参数问题消息。
网络诊断:
- Echo请求与回复:用于ping命令,测试目标主机是否可达及往返时间。
- 路由跟踪:traceroute命令使用ICMP消息来跟踪数据包的路由路径。
网络状态通知:
- 重定向:路由器可以使用ICMP重定向消息告知主机更好的路由选择。
- 源抑制:虽然已不常用,但可用于通知发送方降低发送速率。
地址掩码请求与应答:
- 用于主机向路由器请求子网掩码信息。
路由器公告与请求:
- 用于发现网络中的路由器及其地址。
时间戳请求与应答:
- 用于时间同步和测量网络延迟。
ICMP报文类型:
ICMP消息分为多种类型,每种类型对应不同的功能:
- 类型0和8:回显应答和请求(ping使用)
- 类型3:目标不可达
- 类型5:重定向
- 类型11:超时
ICMP的重要性:
- 网络故障排查:ICMP是网络管理员排查网络问题的重要工具。
- 网络性能优化:通过ICMP可以了解网络状态,帮助优化网络性能。
- 安全考虑:一些网络攻击(如ICMP洪水攻击)也利用ICMP,因此需要合理配置ICMP策略。
ICMP与其他协议的关系:
- ICMP是IP层的一部分,但它不是传输层协议。
- ICMP消息通常被封装在IP数据包中传输。
理解ICMP协议对于网络管理、故障排查和安全配置都非常重要。它提供了网络层面的基本通信机制,确保了IP网络的正常运行和问题诊断。
ping命令的原理
「面试官」:请说明ping命令的原理。
「参考回答」:
ping(Packet Internet Groper)是一个常用的网络诊断工具,用于测试目标主机的可达性和往返时间。它的工作原理主要基于ICMP协议,具体如下:
基本原理:
- ping命令利用ICMP Echo请求和Echo回复消息。
- 发送方发送ICMP Echo请求包到目标主机。
- 如果目标主机可达,它会回复一个ICMP Echo回复包。
详细过程:
- 发送Echo请求:
- ping程序构造一个ICMP Echo请求数据包。
- 这个包含一个标识符和序列号,用于匹配请求和回复。
- 接收Echo回复:
- 目标主机接收到Echo请求后,会构造一个Echo回复包。
- 回复包包含与请求包相同的标识符和序列号。
- 计算往返时间(RTT):
- ping程序记录发送请求和接收回复的时间差。
- 这个时间差就是往返时间(Round-Trip Time, RTT)。
- 结果显示:
- 显示每个回复包的RTT。
- 通常还会显示数据包大小和TTL值。
- 统计信息:
- 在ping结束后,会显示统计信息,如平均RTT、丢包率等。
ping命令的特点:
- 简单有效:快速判断网络连通性。
- 低开销:使用小数据包,对网络负载影响小。
- 跨平台:几乎所有操作系统都支持。
ping的应用:
- 网络故障排查:快速确定网络问题。
- 网络延迟测试:评估网络性能。
- DNS解析验证:ping域名可以验证DNS解析是否正常。
ping的限制:
- 防火墙阻挡:一些防火墙可能会阻止ICMP包。
- 路由配置:某些路由器可能会丢弃或不转发ICMP包。
- 负载均衡:在负载均衡环境中,ping可能无法反映真实情况。
ping命令示例:
$ ping www.example.com PING www.example.com (93.184.216.34): 56 data bytes 64 bytes from 93.184.216.34: icmp_seq=0 ttl=56 time=11.632 ms 64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=11.726 ms 64 bytes from 93.184.216.34: icmp_seq=2 ttl=56 time=10.683 ms ...
ping的工作流程图:
TCP的三次握手机制
「面试官」:请详细介绍一下TCP的三次握手机制。
「参考回答」:
TCP(传输控制协议)的三次握手是建立TCP连接的关键过程,它确保了双方都准备好进行数据交换。这个过程涉及客户端和服务器之间的三次交互:
第一次握手(SYN):
- 客户端发送一个SYN(同步)包到服务器。
- 这个包中包含客户端的初始序列号(ISN)。
- 客户端进入SYN_SENT状态。
第二次握手(SYN+ACK):
- 服务器收到SYN包后,回复一个SYN+ACK包。
- 这个包确认了客户端的SYN,并包含服务器自己的SYN(初始序列号)。
- 服务器进入SYN_RECEIVED状态。
第三次握手(ACK):
- 客户端收到服务器的SYN+ACK后,发送一个ACK包作为响应。
- 这个ACK确认了服务器的SYN。
- 连接建立,双方进入ESTABLISHED状态。
三次握手的重要性:
- 同步序列号:确保双方都知道对方的初始序列号。
- 确认双方的接收和发送能力:通过这个过程,双方都确认了对方能够发送和接收数据。
- 防止旧连接的混淆:避免了已失效的连接请求突然又传到服务器,造成错误。
三次握手的过程图:
理解TCP三次握手机制对于网络编程和故障排查非常重要,它是TCP可靠连接的基础。
TCP握手为什么是三次
「面试官」:TCP握手为什么是三次,为什么不能是两次?不能是四次?
「参考回答」:
TCP握手为什么是三次,这个问题涉及到TCP协议的设计原理和网络通信的可靠性保证。让我们逐点分析:
为什么是三次握手:
- 确认双向通信:三次握手能够确认双方的发送和接收能力都正常。
- 同步序列号:双方都能得知对方的初始序列号(ISN)。
- 防止旧连接请求:可以避免已失效的连接请求突然又传到服务器,引起错误。
为什么不能是两次握手:
- 无法确认客户端的接收能力:如果只有两次握手,服务器无法确认客户端是否已经收到了自己的SYN+ACK包。
- 可能导致资源浪费:如果客户端的SYN包丢失,服务器会一直保持半连接状态,浪费资源。
- 容易受到SYN洪泛攻击:攻击者可以发送大量SYN包而不响应ACK,耗尽服务器资源。
为什么不需要四次握手:
- 效率问题:四次握手会增加建立连接的时间,降低效率。
- 不必要:三次握手已经足够确认双方的收发能力和同步序列号。
- 额外开销:多一次握手意味着多一次网络交互,增加了不必要的开销。
三次握手的充分性:
- 第一次握手:客户端证明了自己的发送能力。
- 第二次握手:服务器证明了自己的接收和发送能力。
- 第三次握手:客户端证明了自己的接收能力,并确认了服务器的发送能力。
通过这三次交互,双方都确认了对方的收发能力,并同步了初始序列号,达到了建立可靠连接的目的。
因此,三次握手是在保证可靠性和效率之间的最佳平衡,既不像两次握手那样不够安全,也不像四次握手那样过于冗余。
TCP四次挥手过程
「面试官」:说说TCP四次挥手过程?
「参考回答」:
TCP的四次挥手是指TCP连接终止时的过程。这个过程确保双方都能够gracefully(优雅地)关闭连接,不会造成数据丢失。让我们详细了解这个过程:
第一次挥手(FIN):
- 主动关闭方(通常是客户端)发送一个FIN包。
- FIN包表示:"我已经没有数据要发送了,但我还可以接收数据。"
- 发送方进入FIN_WAIT_1状态。
第二次挥手(ACK):
- 被动关闭方(通常是服务器)收到FIN包,发送一个ACK作为响应。
- 这个ACK表示:"我知道你想关闭连接了,等我处理完剩余数据就关闭。"
- 被动方进入CLOSE_WAIT状态,主动方收到ACK后进入FIN_WAIT_2状态。
第三次挥手(FIN):
- 被动关闭方处理完所有数据后,发送一个FIN包。
- 这个FIN表示:"我也没有数据要发送了,可以关闭连接了。"
- 被动方进入LAST_ACK状态。
第四次挥手(ACK):
- 主动关闭方收到FIN后,发送一个ACK作为响应。
- 这个ACK表示:"我知道你也准备好关闭了,再见。"
- 主动方进入TIME_WAIT状态,被动方收到ACK后关闭连接。
四次挥手的过程图:
重要概念:
- 半关闭状态:在第二次和第三次挥手之间,连接处于半关闭状态,一方可以继续发送数据。
- TIME_WAIT状态:主动关闭方在发送最后一个ACK后,会等待2MSL(最大报文生存时间)才真正关闭连接。
四次挥手的意义:
- 确保双方都能够完全关闭连接。
- 允许任何一方先发起关闭请求。
- 保证剩余数据能够完全传输。
- 防止旧连接的数据包影响新连接。
理解TCP的四次挥手过程对于正确实现网络应用和诊断网络问题非常重要。
为什么挥手是4次
「面试官」:为什么挥手是4次?
「参考回答」:
TCP挥手过程是4次,而不是3次或其他次数,这与TCP的全双工通信特性以及确保可靠关闭连接的需求有关。让我们详细分析为什么需要4次挥手:
全双工通信的特性:
- TCP连接是全双工的,意味着数据可以在两个方向上独立传输。
- 每个方向都需要单独关闭。
关闭连接的两个阶段:
- 每个方向的关闭都需要一个FIN和一个ACK,因此总共需要4个报文。
为什么不能是3次挥手:
- 如果是3次挥手,无法保证双方都能够完全关闭自己的发送通道。
- 可能导致数据丢失,因为一方可能还有数据要发送。
4次挥手的必要性:
- 第一次挥手(FIN):
- 主动方表示自己不再发送数据。
- 但仍然可以接收数据。
- 第二次挥手(ACK):
- 被动方确认收到关闭请求。
- 此时被动方可能还有数据要发送。
- 第三次挥手(FIN):
- 被动方处理完所有数据后,发送FIN。
- 表示被动方也准备关闭连接。
- 第四次挥手(ACK):
- 主动方确认收到被动方的关闭请求。
- 进入TIME_WAIT状态,等待2MSL后才真正关闭。
4次挥手的优势:
- 确保数据完整性:允许双方都能发送完所有数据。
- 防止连接混淆:TIME_WAIT状态可以防止旧连接的延迟数据包影响新连接。
- 灵活性:允许任何一方先发起关闭请求。
特殊情况:
- 在某些情况下,如果双方同时发起关闭,可能会出现三次挥手的情况,但这是特殊情况,不是标准过程。
总之,4次挥手是为了确保TCP连接的可靠关闭,保证双方都能够安全地终止数据传输,并防止潜在的数据混淆问题。这种设计反映了TCP协议对数据完整性和可靠性的重视。
为什么需要等待2MSL
「面试官」:TCP四次挥手过程中,为什么需要等待2MSL,才进入CLOSED关闭状态?
「参考回答」:
在TCP四次挥手的最后阶段,主动关闭方在发送最后一个ACK后,会进入TIME_WAIT状态,并等待2MSL(Maximum Segment Lifetime,最大报文生存时间)才真正关闭连接。这个设计有几个重要的原因:
1. 确保最后一个ACK能够到达:
- 如果最后一个ACK丢失,被动方会重发FIN。
- 等待2MSL给了足够的时间让可能丢失的ACK重传。
2. 防止旧连接的数据包:
- 等待2MSL可以确保旧连接的所有数据包都已经在网络中消失。
- 防止这些延迟的数据包干扰到新建立的可能使用相同端口的连接。
3. 实现可靠的连接终止:
- 确保双方都正确关闭连接。
- 避免因为网络问题导致的连接状态不一致。
4. 处理FIN对应的ACK丢失情况:
- 如果FIN对应的ACK丢失,被动方会重发FIN。
- 2MSL的等待时间足以处理这种情况。
5. 允许老的重复分节在网络中消逝:
- 防止"已失效的连接请求报文段"出现在本连接中。
为什么是2MSL而不是1MSL:
- 1个MSL确保四次挥手中主动关闭方最后发送的ACK报文最终能够到达对端。
- 另1个MSL确保对端如果没收到ACK,重传的FIN报文能够到达。
MSL的典型值:
- 在Linux系统中,MSL默认值通常是30秒。
- 因此,TIME_WAIT状态一般会持续60秒。
TIME_WAIT状态的潜在问题:
- 在高并发服务器中,大量TIME_WAIT可能会消耗系统资源。
- 可以通过调整内核参数(如tcp_tw_reuse、tcp_tw_recycle)来优化,但需谨慎。
理解2MSL等待的重要性有助于更好地设计和调优网络应用,特别是在需要处理大量短暂TCP连接的高性能服务器环境中。
TCP的粘包和拆包
「面试官」:TCP的粘包和拆包是什么?
「参考回答」:
TCP的粘包和拆包是在进行TCP数据传输时可能遇到的两个常见问题。这些问题源于TCP是面向流的协议,它不保留消息的边界信息。让我们详细了解这两个概念:
粘包(Packet Sticking):
定义:
- 多个小的数据包在传输过程中被合并成一个大的数据包。
原因:
- TCP的Nagle算法:为了提高网络利用率,多个小数据包会被合并。
- 接收方的TCP缓冲区可能会缓存多个数据包,然后一次性读取。
- 发送方的TCP缓冲区可能会将多个send操作的数据合并成一个TCP报文发送。
影响:
- 接收方无法正确区分数据包的边界,可能导致数据解析错误。
拆包(Packet Splitting):
定义:
- 一个大的数据包在传输过程中被分割成多个小的数据包。
原因:
- MTU(最大传输单元)限制:如果数据包大小超过MTU,会被拆分。
- TCP滑动窗口:接收方的窗口大小可能导致大数据包被拆分。
- 网络设备的缓冲区大小限制。
影响:
- 接收方可能收到不完整的数据,需要进行重组。
解决粘包和拆包的方法:
- 定长包:
- 每个数据包固定长度。
- 不足的部分用特定字符填充。
- 包头+包体:
- 在包头中定义数据包的长度。
- 接收方先解析包头,再根据长度读取数据。
- 特殊分隔符:
- 使用特殊字符作为数据包的分隔符。
- 常见于文本协议,如HTTP使用空行分隔头部和主体。
- TLV格式(Type-Length-Value):
- 指定数据类型、长度和值。
- 灵活性高,常用于二进制协议。
- 应用层协议:
- 设计自定义的应用层协议来处理数据边界。
示例代码(Java):
public class MessageProtocol { private static final int HEADER_LENGTH = 4; public static byte[] pack(byte[] data) { int length = data.length; byte[] packet = new byte[HEADER_LENGTH + length]; packet[0] = (byte) ((length >> 24) & 0xFF); packet[1] = (byte) ((length >> 16) & 0xFF); packet[2] = (byte) ((length >> 8) & 0xFF); packet[3] = (byte) (length & 0xFF); System.arraycopy(data, 0, packet, HEADER_LENGTH, length); return packet; } public static byte[] unpack(byte[] packet) { int length = ((packet[0] & 0xFF) << 24) | ((packet[1] & 0xFF) << 16) | ((packet[2] & 0xFF) << 8) | (packet[3] & 0xFF); byte[] data = new byte[length]; System.arraycopy(packet, HEADER_LENGTH, data, 0, length); return data; } }
注意事项:
- 选择解决方案时要考虑性能、可读性和兼容性。
- 在设计网络应用时,应当从一开始就考虑粘包和拆包问题。
- 对于高性能要求的应用,可能需要结合多种方法。
TCP的流量控制
「面试官」:TCP的流量控制有什么?
「参考回答」:
TCP的流量控制是一种防止发送方向接收方发送过多数据而导致接收方无法处理的机制。这是TCP协议实现可靠传输的重要特性之一。让我们详细探讨TCP的流量控制机制:
流量控制的目的:
- 防止发送方发送数据的速度超过接收方处理数据的速度。
- 避免接收方缓冲区溢出,导致数据丢失。
主要机制:滑动窗口
TCP使用滑动窗口(Sliding Window)机制来实现流量控制:
- 接收窗口(rwnd):
- 接收方在TCP首部中的窗口字段告知发送方自己的接收窗口大小。
- 表示接收方当前能够接收的数据量。
- 发送窗口:
- 发送方根据接收方通告的窗口大小调整自己的发送窗口。
- 确保发送的数据量不会超过接收方的处理能力。
- 动态调整:
- 接收方可以动态调整窗口大小,实时反馈自己的处理能力。
流量控制的工作过程:
- 接收方通过TCP头部的窗口字段告知发送方自己的接收窗口大小。
- 发送方根据这个窗口大小,控制已发送但未收到确认的数据量。
- 如果接收窗口为0,发送方停止发送数据,进入持续计时器(persist timer)状态。
- 当接收方准备好接收更多数据时,会发送一个窗口更新。
零窗口和窗口探测:
- 当接收方的接收窗口变为0时,发送方会停止发送数据。
- 发送方会定期发送窗口探测(Window Probe)数据包,询问接收方的窗口大小。
流量控制与拥塞控制的区别:
- 流量控制是端到端的问题,涉及发送方和接收方。
- 拥塞控制是全局性的,涉及整个网络。
示意图:
实现流量控制的关键点:
- 滑动窗口算法:
- 维护一个可变大小的窗口,表示可以发送的数据量。
- 确认机制:
- 接收方通过确认(ACK)来通知发送方数据已成功接收。
- 超时重传:
- 如果在一定时间内没有收到确认,发送方会重新发送数据。
- 快速重传:
- 如果接收方收到乱序数据,会立即发送重复ACK,触发快速重传。
流量控制的优化:
- Nagle算法:合并小数据包,减少网络传输次数。
- 延迟确认:接收方不立即发送ACK,等待一段时间或数据累积到一定量再确认。
- 选择性确认(SACK):允许接收方确认非连续的数据块,提高重传效率。
理解TCP的流量控制机制对于网络编程和性能优化非常重要。它确保了数据传输的可靠性和效率,是TCP协议设计的核心部分之一。
半连接队列和SYN Flood攻击
「面试官」:说说半连接队列和SYN Flood攻击的关系。
「参考回答」:
半连接队列和SYN Flood攻击是密切相关的两个概念,它们涉及TCP连接建立过程中的安全问题。让我们深入探讨这两个概念及其关系:
半连接队列(SYN Queue):
定义:
- 存储处于SYN_RECV状态的连接请求的队列。
- 这些连接已经接收到SYN包,但还未完成三次握手。
特点:
- 大小通常由系统参数控制(如Linux中的
net.ipv4.tcp_max_syn_backlog
)。 - 用于管理正在进行三次握手的连接。
SYN Flood攻击:
定义:
- 一种拒绝服务(DoS)攻击,攻击者发送大量SYN包但不完成握手。
攻击原理:
- 攻击者快速发送大量SYN包,通常使用伪造的源IP地址。
- 服务器为每个SYN包创建半连接,占用系统资源。
- 攻击者不回应ACK,导致这些半连接长时间占用资源。
半连接队列和SYN Flood的关系:
- 资源耗尽:
- SYN Flood攻击的目标是填满半连接队列。
- 当队列满时,服务器无法处理新的合法连接请求。
- 系统负载:
- 大量半连接会消耗服务器的内存和CPU资源。
- 可能导致系统性能下降或崩溃。
- 连接超时:
- 半连接有生存时间,但在高强度攻击下,超时清理可能跟不上新建连接的速度。
防御SYN Flood攻击的方法:
- SYN Cookies:
- 不在收到SYN时立即分配资源,而是通过特殊的序列号编码连接信息。
- 有效减少了对半连接队列的依赖。
- 增加半连接队列大小:
- 提高系统能够处理的并发SYN请求数量。
- 但这只能在一定程度上缓解问题,不能根本解决。
- 减少SYN超时时间:
- 加快半连接的超时清理,但可能影响正常连接。
- 防火墙和IPS:
- 使用网络设备检测和过滤可疑的SYN包。
- TCP SYN Proxy:
- 代理服务器完成初始的TCP握手,只有完成三次握手后才将连接转发给实际服务器。
- 限制单IP的SYN包速率:
- 通过配置防火墙规则来实现。
示意图:
代码示例(Python中使用SYN Cookies):
import socket def create_socket_with_syn_cookies(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_TCP, socket.TCP_DEFER_ACCEPT, 1) return sock # 使用 server_socket = create_socket_with_syn_cookies() server_socket.bind(('0.0.0.0', 8080)) server_socket.listen(5)
理解半连接队列和SYN Flood攻击的关系对于网络安全和服务器配置非常重要。它不仅涉及到如何防御特定类型的攻击,还关系到如何优化TCP连接的处理以提高服务器的性能和稳定性。
TCP的滑动窗口
「面试官」:TCP的滑动窗口是什么?
「参考回答」:
TCP的滑动窗口(Sliding Window)是一种流量控制机制,用于优化数据传输效率和网络利用率。它允许发送方在接收到接收方的确认(ACK)之前连续发送多个数据包,从而提高网络吞吐量。让我们深入了解TCP滑动窗口的概念和工作原理:
滑动窗口的定义:
- 滑动窗口是指无需等待确认应答而可以继续发送数据的最大值。
- 它是一个可以动态调整的范围,随着数据的发送和确认而不断移动。
滑动窗口的组成:
- 已发送并收到ACK的数据:窗口左边缘左侧的数据。
- 已发送但未收到ACK的数据:窗口内的左部分。
- 允许发送但尚未发送的数据:窗口内的右部分。
- 不允许发送的数据:窗口右边缘右侧的数据。
滑动窗口的工作原理:
- 发送方维护一个发送窗口,接收方维护一个接收窗口。
- 发送方可以发送窗口内的所有数据,无需等待每个包的ACK。
- 当收到ACK时,窗口向右滑动,可以发送新的数据。
- 接收方通过TCP头部的窗口字段告知发送方自己的接收窗口大小。
滑动窗口的优势:
- 提高传输效率:允许批量发送和确认数据。
- 减少网络拥塞:通过调整窗口大小来控制发送速率。
- 实现流量控制:防止发送方overwhelm接收方。
滑动窗口与拥塞控制的关系:
- 滑动窗口主要用于流量控制。
- 拥塞窗口(cwnd)与接收窗口(rwnd)共同决定实际的发送窗口大小。
滑动窗口的实现细节:
- 窗口大小:
- 由接收方advertised window和拥塞窗口(cwnd)的最小值决定。
- 实际发送窗口 = min(rwnd, cwnd)
- 窗口满和窗口空:
- 窗口满:已发送但未确认的数据量达到窗口大小。
- 窗口空:所有已发送的数据都得到了确认。
- 窗口更新:
- 接收方通过ACK包中的窗口字段通知发送方自己的接收能力。
- 零窗口:
- 当接收方的接收窗口变为0时,发送方停止发送数据。
- 发送方会定期发送窗口探测(Window Probe)包。
滑动窗口的优化技术:
- Nagle算法:
- 合并小数据包,减少网络传输次数。
- 可能增加延迟,不适用于需要实时响应的应用。
- 延迟确认:
- 接收方不立即发送ACK,等待一定时间或数据累积。
- 减少ACK包的数量,提高网络效率。
- 快速重传和快速恢复:
- 在收到三个重复ACK时立即重传,不等待超时。
- 快速恢复避免拥塞窗口急剧减小。
- 选择性确认(SACK):
- 允许接收方确认非连续的数据块。
- 提高了网络利用率,特别是在高丢包率的网络中。
滑动窗口的图示:
滑动窗口在实际应用中的考虑:
- 窗口大小的选择:
- 太小会导致网络利用率低。
- 太大可能导致网络拥塞。
- 与应用层的交互:
- 需要考虑应用层的数据生成速度和消费速度。
- 网络环境适应:
- 在不同的网络条件下(如高延迟、高丢包率),可能需要调整窗口策略。
- 安全性考虑:
- 滑动窗口机制可能被用于某些攻击,如TCP序列号预测攻击。
代码示例(Python中模拟滑动窗口):
class SlidingWindow: def __init__(self, size): self.size = size self.buffer = [None] * size self.head = 0 self.tail = 0 def add(self, item): if self.is_full(): return False self.buffer[self.tail] = item self.tail = (self.tail + 1) % self.size return True def remove(self): if self.is_empty(): return None item = self.buffer[self.head] self.buffer[self.head] = None self.head = (self.head + 1) % self.size return item def is_full(self): return self.head == (self.tail + 1) % self.size def is_empty(self): return self.head == self.tail # 使用示例 window = SlidingWindow(5) for i in range(5): window.add(i) print(window.remove()) # 输出: 0 window.add(5) # 滑动窗口移动
理解TCP滑动窗口机制对于网络编程、性能优化和故障排查都非常重要。它是TCP实现高效、可靠数据传输的核心机制之一,在现代网络通信中扮演着关键角色。