计算机网络

发布于:2025-08-08 ⋅ 阅读:(17) ⋅ 点赞:(0)

网络OSI模型和TCP/IP模型

OSI七层模型
为了使得多种设备能通过网络相互通信,解决各种不同设备在网络互联中的兼容性问题,制定了OSI网络模型。
在这里插入图片描述

  • 应用层:负责给应用程序提供统一的接口。
  • 表示层:负责把数据转换成兼容另一个系统能识别的格式。
  • 会话层:负责建立、管理和终止表示层实体之间的通信会话。
  • 传输层:负责端到端的数据传输。
  • 网络层:负责数据的路由、转化、分片。
  • 数据链路层:负责数据的封帧和差错检测,以及MAC寻址。
  • 物理层:负责在物理网络中传输数据帧。

TCP/IP模型
在这里插入图片描述

  • 应用层:支持HTTP、SMTP等最终用户进程。
  • 传输层:处理主机到主机的通信(TCP、UDP)。
  • 网络层:寻址和路由数据包(IP协议)。
  • 链路层:通过网络的物理电线、电缆或无线信道移动比特。

HTTP报文有哪些部分?

在这里插入图片描述
请求报文

  • 请求行:请求方法、请求目标(URL或URI)和HTTP协议版本。
  • 请求头部:关于请求的附加信息,如Host,User-Agent、Content-Type等。
  • 空行:请求头部和请求体之间用空行分隔。
  • 请求体:包含请求的数据,通常用于POST请求等需要传输数据的情况。

响应报文

  • 状态行:HTTP协议版本、状态码和状态信息。
  • 响应头部:关于响应的附加信息,如Content-Type、Content-Length等。
  • 空行:响应头部和响应体之间用空行分隔。
  • 响应体:响应的数据,通常是服务器返回的HTML、JSON等内容。

HTTP常用的状态码

在这里插入图片描述
常见的具体状态码:

  • 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:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器收到响应。

HTTP层请求的类型有哪些?

  • GET:用于请求获取指定资源,通常用于获取数据。
  • POST:用于向服务器提交数据,通常用于提交表单数据或进行资源的创建。
  • PUT:向服务器更新指定资源,通常用于更新已存在的资源。
  • DELETE:用于请求服务器删除指定资源。
  • HEAD:类似于GET请求,但只返回资源的头部信息,用于获取资源的元数据而不获取实际内容。

GET和POST的使用场景,有哪些区别?

GET的语义是从服务器获取指定的资源。GET请求的参数位置一般是写在URL中,URL规定只能支持ASCII,所以GET请求的参数只允许ASCII字符,而且浏览器会对URL的长度有限制(HTTP协议本身对URL长度并没有做任何规定)。
在这里插入图片描述
POST的语义是根据请求负荷(报文body)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST请求携带数据的位置一般是写在报文body中,body中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对body大小做限制。
在这里插入图片描述

  • GET方法是安全幂等的,可以对GET请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上,而且在浏览器中GET请求可以保存为书签。
  • POST请求是不安全的,不幂等的,浏览器一般不会缓存POST请求,也不能把POST请求保存为书签。

HTTP的长连接是什么?

HTTP协议采用的是请求-问答 的模式。
在这里插入图片描述
由于HTTP是基于TCP传输协议实现的,客户端与服务端要进行HTTP通信前,需要先建立TCP连接,然后客户端发送HTTP请求,服务端收到后就会返回响应,至此请求-应答的模式就完成了,随后就会释放TCP连接。
在这里插入图片描述
如果每次请求都要经历这样的过程:建立TCP -> 请求资源 -> 响应资源 -> 释放资源,那么此方式就是HTTP短连接
在这里插入图片描述
HTTP长连接:使用同一个TCP连接来发送和接收多个HTTP请求/应答,避免了连接建立和释放的开销。
在这里插入图片描述
HTTP长连接的特点是:只要任意一端没有明确提出端来连接,则保持TCP连接状态。

HTTP1.1怎么对请求做拆包?

在HTTP/1.1中,请求的拆包是通过”Content-Length"头字段来进行的。该字段指示了请求正文的长度,服务器可以根据该长度来正确接收和解析请求。
在这里插入图片描述

HTTP断点重传

实现断点续传的功能,需要客户端记录下当前的下载进度,并在需要续传的时候通知服务端本次需要下载的内容片段。
断点续传中4个HTTP头是不可少的:Range头,Content-Range头,Accept-Range头,Content-Length头。其中第一个Range头是客户端发送过来的,后面3个头需要服务端发送给客服端。

  • Accept-Ranges:bytes:这个值声明了可被接受的每个范围请求,大多数情况下是字节数bytes
  • Range:bytes=开始位置-结束位置:Range是浏览器告知服务器所需部分内容范围的消息头。

HTTP为什么不安全?

HTTP是明文传输,存在三个风险:

  • 窃取风险:通信链路上可以获取通信内容,用户号容易没。
  • 篡改风险:强制植入垃圾广告,视觉污染,用户眼容易瞎。
  • 冒充风险:冒充淘宝网站,用户钱容易没。

在这里插入图片描述

HTTPS在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第一次握手
首先,有客户端向服务端发起加密通信请求,在这一步,客户端主要向服务器发送以下信息:

  • 客户端支持的TLS版本协议。
  • 客户端生产的随机数(Client Random),后面用于生成会话密钥条件之一。
  • 客户端支持的密码套件列表。

TLS第二次握手
服务端收到客户端请求后,向客户端发出响应。服务端回应的内容有如下内容:

  • 确认TLS协议版本,如果浏览器不支持,则关闭加密通信。
  • 服务器生产的随机数(Server Random),也是后面用于生产会话密钥条件之一。
  • 确认的密码套件列表,如RSA加密算法。
  • 服务器的数字证书。

TLS第三次握手
客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的CA公钥,确认服务器的数字证书的真实性。
如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:

  • (1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。
  • (2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
  • (3)客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。

上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。

服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」。

TLS第四次握手
服务器收到客户端的第三个随机数之后,通过协商的加密算法,计算出本次通信的会话密钥
然后,向客户端发送最后的信息:

  • (1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
  • (2)服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」加密内容。

HTTPS是如何防范中间人的攻击?

主要是通过加密和身份校验机制防范中间人攻击的:

  • 加密:https握手期间会通过非对称加密的方式来协商出对称加密密钥。
  • 身份校验:服务器会向证书颁发机构申请数字证书,证书中包含了服务器的公钥和其他相关信息。当客户端与服务器建立连接时,服务器会将证书发送给客户端。客户端会验证证书的合法性,包括检查证书的有效期、颁发机构的信任等。如果验证通过,客户端会使用证书中的公钥来加密通信数据,并将加密后的数据发送给服务器,然后由服务端用私钥解密。

中间人攻击的关键在于攻击者冒充服务器与客户端建立连接,并同时与服务器建立连接。

但由于攻击者无法获取服务器的私钥,因此无法正确解密客户端发送的加密数据。同时,客户端会在建立连接时验证服务器的证书,如果证书验证失败或存在问题,客户端会发出警告或中止连接。

Http1.1和2.0的区别是什么?

  • 头部压缩:HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
  • 二进制格式:HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame)。这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率
  • 并发传输:引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。解决了 HTTP/1.1 队头阻塞的问题:
  • 服务器主动推送资源:HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务端不再是被动地响应,可以主动向客户端发送消息。

HTTP进行TCP连接之后,在什么情况下会中断

  • 当服务端或者客户端执行close系统调用的时候,会发送FIN报文,就会进行四次挥手的过程。
  • 当发送方发送了数据之后,接收方超过一段时间没有响应ACK报文,发送方重传数据达到最大次数的时候,就会断开TCP连接。
  • 当HTTP长时间没有进行请求和响应的时候,超过一定的时间,就会释放连接。

HTTP、SCOKET和TCP的区别

  • HTTP是一种用于超文本数据的应用层协议,用于在客户端和服务端之间传输和显示web页面。
  • Socket是计算机网络中的一种抽象,用于描述通信链路的一端,提供了底层的通信接口,可实现不同计算机之间的数据交换。
  • TCP是一种面向连接的、可靠的传输层协议,负责在通信的两端之间建立可靠的数据传输连接。

DNS

DNS的全称是Domain Name System (域名系统),它是互联网中用于将域名转换为对应IP地址的分布式数据库系统。DNS扮演着重要的角色,使得人们可以通过易记的域名访问互联网资源,而无需记住复杂的IP地址。

域名的层次关系类似一个树状结构:

  • 根DNS服务器(.)
  • 顶级域DNS服务器(.com)
  • 权威DNS服务器(server.com)

在这里插入图片描述
客户端只要能够找到任意一台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的默认端口是53

DNS的底层使用的是TCP还是UDP?

DNS基于UDP协议实现,DNS使用UDP协议进行域名解析和数据传输。因为基于UDP实现DNS能够提供低延迟、简单快速、轻量级的特性,更适合DNS这种需要快速响应的域名解析服务。

  • 低延迟:UDP是一种无连接的协议,不需要再数据传输前建立连接,因此可以减少传输时延,适合DNS这种需要快速响应的应用场景。
  • 简单快速:UDP相对于TCP更简单,没有TCP的连接管理和流量控制机制,传输效率更高,适合DNS这种需要快速传输数据的场景。
  • 轻量级:UDP头部较小,占用较少的网络资源,对于小型请求和响应来说更加轻量级,适合DNS这种频繁且短小的数据交换。

尽管UDP存在丢包和数据包损坏的风险,但在DNS的设计中,这些风险是可以容忍的。DNS使用了一些机制来提高可靠性,例如查询超时重传、请求重试、缓存等,以确保数据传输的可靠性和正确性。

HTTP到底是不是无状态的?

HTTP是无状态的,这意味着每个请求都是独立的,服务器不会在多个请求之间保留关于客户端状态的信息。在每个HTTP请求中,服务器不会记住之前的请求或会话状态,因此每个请求都是相对独立的。

虽然HTTP本身是无状态的,但可以通过一些机制来实现状态保持,其中最常见的方式是使用Cookie和Session来跟踪用户状态。通过在客户端存储会话信息或状态信息,服务器可以识别和跟踪特定用户的状态,以提供一定程度的状态保持功能。

Cookie和Session有什么区别?

对比维度 Cookie Session
存储位置 数据存储在客户端(通常是浏览器),浏览器发请求时自动附带Cookie数据 数据存储在服务器端,服务器为每个用户分配唯一Session ID,ID通过Cookie或URL重写发给客户端,客户端后续请求带该ID,服务器依ID查Session数据
数据容量 单个大小通常限4KB左右,多数浏览器对每个域名的总Cookie数量也有限制 存储在服务器,理论不受数据大小限制,主要受限服务器内存大小
安全性 相对不安全,易受XSS(跨站脚本攻击)威胁,设HttpOnly属性可防JavaScript访问、减XSS风险,但仍可能受CSRF(跨站请求伪造)攻击 通常认为更安全,敏感数据存服务器端,但需防范Session劫持(获他人Session ID)和会话固定攻击
生命周期 可设过期时间,过期自动删除;也可设为会话Cookie,浏览器关闭时自动删除 默认用户关闭浏览器时结束,服务器也可设超时时间,超时间未活动则失效
性能 数据随每个请求发服务器,Cookie数据大时可能影响网络传输效率 数据存服务器端,每次请求需查询服务器上Session数据,高并发场景可能增加服务器负载

token、session、cookie的区别

  • session存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号sessionId,通常存放于cookie中。服务器收到cookie后解析出sessionId,再去session列表中查找,才能找到相应session,依赖cookie。
  • cookie类似一个令牌,装有sessionId,存储在客户端,浏览器通常会自动添加。
  • token也类似一个令牌,无状态,用户信息都被加密到token中,服务器收到token后解密就可知道是哪个用户,需要开发者手动添加。

如果把数据存储在LocalStorage,和Cookie有什么区别?

对比维度 Cookie LocalStorage
存储容量 通常较小,每个大小限制在几KB左右 通常较大,一般限制在几MB左右,适合存储大量数据
数据发送 每次HTTP请求中自动发送到服务器,适合客户端与服务器间传递数据 仅在浏览器端存储,不会自动发送到服务器,适合同一域名下不同页面间共享数据
生命周期 可设置过期时间,到期自动过期 永久存储在浏览器,除非通过JavaScript代码手动删除
安全性 安全性较低,每次HTTP请求自动发服务器,存在被窃取或篡改风险 相对更安全,仅在浏览器端存储,不自动发服务器

什么数据应该存在cookie,什么数据应该存放在Localstorage?

Cookie适合用于在客户端和服务器之间传递数据、跨域访问和设置过期时间,而LocalStorage适合用于在同一域名下的不同页面之间共享数据、存储大量数据和永久存储数据。

JWT令牌和传统方式有什么区别?

  • 无状态性:JWT是无状态的令牌,不需要在服务端存储会话信息。相反,JWT令牌中包含了所有必要的信息,如用户身份、权限等。这使得JWT在分布式系统中更加适用,可以方便进行扩展和跨域访问。
  • 安全性:JWT适用密钥对令牌进行签名,确保令牌的完整性和真实性。只有持有正确密钥的服务器才能对令牌进行验证和解析。这种方式比传统的基于会话和Cookie的验证更加安全,有效防止了CSRF(跨站请求伪造)等攻击。
  • 跨域支持:JWT令牌可以在不同域之间传递,适用于跨域访问的场景。通过在请求的头部或参数中携带JWT令牌,可以实现无需Cookie的跨域身份验证。

JWT令牌都有哪些字段?

JWT令牌由三个部分组成:头部(Header)载荷(Payload)签名(Signature)。其中,头部和载荷均为JSON格式,适用Base64编码进行序列化,而签名部分是对头部、载荷和密钥进行签名后的结果。
在这里插入图片描述

JWT令牌为什么能解决集群部署,什么是集群部署?

JWT令牌通过在令牌中包含所有必要的身份验证和会话信息,使得服务器无需存储会话信息,从而解决了集群部署中的身份验证和会话管理问题。

JWT令牌是=自包含的,服务器可以独立地对令牌进行验证,而不需要依赖其他服务器或共享存储。这使得集群中的每个服务器都可以独立处理请求,提高了系统的可伸缩性和容错性。

JWT的缺点是什么?

JWT一旦派发出去,在失效之前都是有效的,没办法及时撤销JWT。

要解决这个问题,可以在业务层增加判断逻辑,使用内存数据库维护一个黑名单,如果想让某个JWT失效的话就直接将这个JWT加入到黑名单中。每次使用JWT进行请求的话都会先判断这个JWT是否存在于黑名单中。

JWT令牌如果泄漏了,怎么解决?

  • 及时失效令牌:当检测到JWT令牌泄露或存在风险时,可以立即将令牌标记为失效状态。服务器在接收到带有失效标记的令牌时,会拒绝对其进行任何操作,从而保护用户的身份和数据安全。
  • 刷新令牌:JWT令牌通常具有一定的有效期,过期后需要重新获取新的令牌。当检测到令牌泄露时,可以主动刷新令牌,即重新生成一个新的令牌,并将旧令牌标记为失效状态。这样,即使泄露的令牌被恶意使用,也会很快失效,减少了被攻击者滥用的风险。
  • 使用黑名单:服务器可以维护一个令牌的黑名单,将泄露的令牌添加到黑名单中。在接收到令牌时,先检查令牌是否在黑名单中,如果在则拒绝操作。这种方法需要服务器维护黑名单的状态,对性能有一定的影响,但可以有效地保护泄露的令牌不被滥用。

前端是如何存储JWT的?

存储类型 优点 缺点
Local Storage(本地存储) 提供较大存储空间(一般为5MB ),数据不会随HTTP请求发送到服务器,不会出现在HTTP缓存或日志中 存在XSS(跨站脚本攻击)风险,恶意脚本可通过JavaScript访问存储的JWT,盗取用户凭证
Session Storage(会话存储) 与Local Storage类似,数据仅限当前浏览器窗口或标签页,窗口关闭后数据清除,一定程度减少数据泄露风险 用户体验可能受影响,刷新页面或新标签页打开应用需重新认证
Cookie 可设HttpOnly标志防JavaScript访问,减少XSS攻击风险;设Secure标志确保仅HTTPS发送,增安全性 大小限制小(通常4KB ),每次HTTP请求携带,可能影响性能;设置不当可能受CSRF(跨站请求伪造)攻击

为什么又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性能要更好。
  • HTTP/2.0在HTTP/1.1的基础上做了优化,性能可能比很多RPC协议都要好。

HTTP长连接与WebSocket有什么区别?

  • 全双工和半双工:TCP协议本身是全双工的,但是常用的HTTP/1.1,虽然是基于TCP的协议,但是它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,都不太友好,因此需要使用支持全双工的WebSocket协议。
  • 应用场景区别:在HTTP/1.1里,只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式实现服务器推送的效果。对于客户端和服务端之间需要频繁交互的复杂场景,可以考虑使用websocket协议。

Nginx有哪些负载均衡算法?

  • 轮询:按照顺序依次将请求分配给后端服务器。
  • IP哈希:根据客户端IP地址的哈希值来确定分配请求的后端服务器。适用于需要保持同一客户端的请求始终发送到同一台后端服务器的场景。
  • URL哈希:按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。
  • 最短响应时间:按照后端服务器的响应时间来分配请求,响应时间短的优先分配。适用于后端服务器性能不均的场景,能够将请求发送到响应时间快的服务器,实现负载均衡。
  • 加权轮询:按照权重分配请求给后端服务器,权重越高的服务器获取更多的请求。适用于后端服务器性能不同的场景,可以根据服务器权重分配请求,提高高性能服务器的利用率。

TCP的头部

在这里插入图片描述
序列号:在建立连接时由计算机生成的随机数作为其初始值,通过SYN包传给接收端主机,每发送一次数据,就累加一次该数据字节数的大小。用来解决网络包乱序问题

确保应答号:下一次期望收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。

控制位:

  • ACK:该位为1时,确认应答的字段变为有效,TCP规定除了最初建立连接时的SYN包之外该位必须设置为1。
  • PST:该位为1时,表示TCP连接中出现异常必须强制断开连接。
  • SYN:该位为1时,表示希望建立连接,并在其序列号的字段进行序列号初始值的设定。
  • FIN:该位为1时,表示今后不会再有数据发送,希望断开连接。当通过结束希望断开连接时,通过双方的主机之间就可以相互交换FIN位为1的TCP段。

TCP三次握手

在这里插入图片描述

  • 一开始,客户端和服务端都处于CLOSE状态。先是服务端主动监听某个端口,处于LISTEN状态。
    在这里插入图片描述
  • 客户端会随机初始化序号(client_isn),将此序号置于TCP首部的序号字段中,同时把SYN标志位置为1,表示SYN报文。接着把第一个SYN报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN-SENT状态。
    在这里插入图片描述
  • 服务端收到客户端的SYN报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入TCP首部的序号字段中,其次把TCP首部的确认应答号字段填入client_isn +1,接着把SYN和ACK标志位置为1。最后把该报文发送给客户端,该报文也不包含应用层数据,之后服务端处于SYN-RCVD状态。
    在这里插入图片描述
  • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文TCP首部ACK标志位置为1,其次确认应答号字段填入server_isn+1,最后把报文发送给服务端,这次报文可以携带客户到服务端的数据,之后客户端处于ESTABLISHED状态。
  • 服务端收到客户端的应答报文后,也进入ESTABLISHED状态。

一旦完成三次握手,双方都处于ESTABLISHED状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。

TCP为什么需要三次握手建立连接?

  • 避免历史连接
    在这里插入图片描述

  • 同步双方初始序列号

  • 在这里插入图片描述

  • 避免资源浪费
    在这里插入图片描述

TCP三次握手,客户端第三次发送的确认包丢失了会发生什么?

当第三次握手丢失了,如果服务端那一方迟迟收不到这个确认报文,就会触发超时重传机制,重传SYN-ACK报文,直到收到第三次握手,或者到达最大重传次数。
ACK报文是不会有重传的,当ACK丢失了,就由对方重传对应的报文。
在这里插入图片描述
当服务端超时重传2次SYN-ACK报文后,由于tcp_synack_retries为2,已达到最大重传次数,于是再等待一段时间(时间为上一次超时时间的2倍),如果还是没能收到客户端的第三次握手(ACK报文),那么服务端就会断开连接。

三次握手和accept是什么关系?accept做了哪些事情?

tcp完成三次握手后,连接会被保存到内核的全连接队列,调用accept就是从把连接取出来给用户程序使用
在这里插入图片描述

客户端发送的第一个SYN报文,服务器没有收到怎么办?

客户端在发送第一个SYN报文后,进入到SYN_SENT状态。如果客户端迟迟收不到服务端的SYN-ACK报文(第二次握手),就会触发超时重传机制,重传SYN报文,而且重传的SYN报文的序列号都是一样的
在这里插入图片描述
当客户端超时重传3次SYN报文后,由于tcp_syn_retries为3,已达到最大重传次数,于是再等待一段时间(时间为上一次超时时间的2倍),如果还是没能收到服务端的第二次握手(SYN-ACK报文),那么客户端就会断开连接。

服务器收到了第一个SYN报文,回复的SYN+ACK报文丢失了怎么办?

当服务端收到客户端的第一次握手后,就会回SYN-ACK报文给客户端,这个就是第二次握手,此时服务端会进入SYN_RCVD状态。

  • 如果客户端迟迟没有收到第二次握手,那么客户端会觉得可能自己的SYN报文(第一次握手)丢失了,于是客户端就会触发超时重传,重传SYN报文
  • 如果第二次握手失败,服务端就收不到第三次握手,于是服务端会触发超时重传机制,重传SYN-ACK报文
    在这里插入图片描述
  • 当客户端超时重传1次SYN报文后,由于tcp_syn_retries为1,已达到最大重传次数,于是再等待一段时间(时间为上一次超时时间的2倍),如果还是没能收到服务端的第二次握手(SYN-ACK报文),那么客户端就会断开连接。
  • 当服务端超时重传2次SYN-ACK报文后,由于tcp_synack_retries为2,已达到最大重传次数,于是再等待一段时间(时间为上一次超时时间的2倍),如果还是没能收到客户端的第三次握手(ACK报文),那么服务端就会断开连接。

第一次握手,客户端发送SYN报文后,服务端回复ACK报文,那这个过程中服务端内部做了哪些工作?

服务端收到客户端发起的SYN请求后,内核会把该连接存储到半连接队列,并向客户端响应SYN-ACK,接着客户端会返回ACK,服务端收到第三次握手的ACK后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到accept队列,等待进程调用accept函数时把连接取出来。
在这里插入图片描述
不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回RST包。

大量SYN包发送给服务端,服务端会发生什么事情?

有可能会导致TCP半连接队列打满,这样当TCP半连接队列满了,后续再收到SYN报文就会丢弃,导致客户端无法和服务端建立连接。

避免SYN攻击方式,有四种方法:

  • 调大netdev_max_backlog。(当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。控制该队列的最大值的参数)
  • 增大TCP半连接队列。
  • 开启net.ipv4.tcp_syncookies(不使用SYN半连接队列的情况下成功建立连接)。
    在这里插入图片描述
  • 减少SYN+ACK重传次数
    减少SYN-ACK的重传次数,以加快处于SYN-REVC状态的TCP连接断开。

TCP四次挥手

在这里插入图片描述

  • 客户端主动调用关闭连接的函数,于是就会发送FIN报文,这个FIN报文代表客户端不会再发送数据了,进入FIN_WAIT_1状态。
  • 服务端收到了FIN状态,然后马上回复一个ACK确认报文,此时服务端进入CLOSE_WAIT状态。在收到FIN报文的时候,TCP协议栈会为FIN包插入一个文件结束符EOF到接收缓冲区中,服务端应用程序可以通过read调用来感知这个FIN包,这个EOF会被放在已排队等候的其他已接收的数据之后,所以必须要继续read接收缓冲区已接收的数据。
  • 接着,当服务端在read数据的时候,最后自然就会读到EOF,接着**read()就会返回0,这时服务端应用程序如果有数据要发送的话,就发完数据后才调用关闭连接的函数,如果服务端应用程序没有数据要发送的话,可以直接调用关闭连接的函数,**这时服务端就会发一个FIN包,这个FIN报文代表服务端不会再发送数据了,之后处于LAST_ACK状态。
  • 客户端接收到服务端的FIN包,并发送ACK确认包给服务端,此时客户端将进入TIME_WAIT状态,
  • 服务端接收到ACK确认包后,就进入了最后的CLOSE状态。
  • 客户端经过2MSL时间之后,也进入CLOSE状态。

为什么4次握手中间两次不能变成一次?

服务器收到客户端的FIN报文时,内核会马上回一个ACK应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送FIN报文,而是将发送FIN报文的控制权交给服务端应用程序。

  • 如果服务端应用程序有数据要发送的话,就发完数据后,才调用关闭连接的函数。
  • 如果服务端应用程序没有数据要发送的话,可以直接调用关闭连接的函数。

第二次和第三次挥手能合并吗?

当被动关闭方在TCP挥手过程中,没有数据要发送并且开启了TCP延迟确认机制,那么第二和第三挥手就会合并传输,这样就出现了三次挥手。

第三次挥手一直没发,会发生什么?

当主动方收到 ACK 报文后,会处于 FIN_WAIT2 状态,就表示主动方的发送通道已经关闭,接下来将等待对方发送 FIN 报文,关闭对方的发送通道。

这时,如果连接是用 shutdown 函数关闭的,连接可以一直处于 FIN_WAIT2 状态,因为它可能还可以发送或接收数据。但对于 close 函数关闭的孤儿连接,由于无法再发送和接收数据,所以这个状态不可以持续太久,而 tcp_fin_timeout 控制了这个状态下连接的持续时长,默认值是 60 秒:

它意味着对于孤儿连接(调用close关闭的连接),如果在60秒后还没有收到FIN报文,连接就会直接关闭。

第二次和第三次挥手之间,主动断开的那端能干什么

如果主动断开的一方,是调用了shutdown函数来关闭连接,并且只选择了关闭发送能力且没有关闭接收能力的话,那么主动断开的一方在第二次和第三次挥手之间还可以接收数据。
在这里插入图片描述

断开连接时客户端FIN包丢失,服务端的状态是什么?

如果第一次挥手丢失了,那么客户端迟迟收不到被动方的 ACK 的话,也就会触发超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数控制。

当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,则会在等待一段时间(时间为上一次超时时间的 2 倍),如果还是没能收到第二次挥手,那么客户端直接进入到 close 状态,而服务端还是 ESTABLISHED状态
在这里插入图片描述

为什么四次挥手之后要等2MSL?

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 状态的连接可以应对。

TCP和UDP区别是什么?

对比项 TCP UDP
连接 面向连接,传输数据前先建立连接 不需要连接,即刻传输数据
服务对象 一对一的两点服务,一条连接只有两个端点 支持一对一、一对多、多对多的交互通信
可靠性 可靠交付数据,数据可无差错、不丢失、不重复、按序到达 尽最大努力交付,不保证可靠交付数据,可基于其实现可靠传输协议(如QUIC协议 )
拥塞控制、流量控制 有拥塞控制和流量控制机制,保证数据传输安全性 没有,网络拥堵不影响发送速率
首部开销 首部长度较长,无“选项”字段时20字节,有则变长 首部只有8个字节,固定不变,开销较小
传输方式 流式传输,无边界,保证顺序和可靠 一个包一个包发送,有边界,可能丢包和乱序

TCP为什么可靠传输?

  • 连接管理:即三次握手和四次挥手。连接管理机制能够建立起可靠的连接,这是保证传输可靠性的前提。
  • 序列号:TCP将每个字节的数据都进行了编号,这就是序列号。序列号的具体作用如下:能够保证可靠性,既能防止数据丢失,又能避免数据重复。能够保证有序性,按照序列号顺序进行数据包还原。能够提高效率,基于序列号可实现多次发送,一次确认。
  • 确认应答:接收方接收数据之后,会回传ACK报文,报文中带有此次确认的序列号,用于告知发送方此次接收数据的情况。在指定时间后,若发送端仍未收到确认应答,就会启动超时重传。
  • 超时重传:超时重传主要有两种场景:数据包丢失:在指定时间后,若发送端仍未收到确认应答,就会启动超时重传,向接收端重新发送数据包。确认包丢失:当接收端收到重复数据(通过序列号进行识别)时将其丢弃,并重新回传ACK报文。
  • 流量控制:接收端处理数据的速度是有限的,如果发送方发数据的速度过快,就会导致接收端的缓冲区溢出,进而导致丢包。为了避免上述情况的发生,TCP支持根据接收端的处理能力,来决定发送端的发送速度。这就是流量控制。流量控制是通过在TCP报文段首部维护一个滑动窗口来实现的。
  • 拥塞控制:拥塞控制就是当网络拥堵严重时,发送端减少数据发送。拥塞控制是通过发送端维护一个拥塞窗口来实现的。可以得出,发送端的发送速度,受限于滑动窗口和拥塞窗口中的最小值。拥塞控制方法分为:慢开始,拥塞避免、快重传和快恢复。

怎么使用udp实现http?

UDP是不可靠的,但基于UDP的QUIC协议可以实现类似TCP的可靠性传输,在http3就用了quic协议。

  • 连接迁移:QUIC支持在网络变化时快速迁移连接。
  • 重传机制:QUIC使用重传机制来确保丢失的数据包能够被重新发送,从而提高数据传输的可靠性。
  • 前向纠错:QUIC可以使用前向纠错技术,在接收端修复部分丢失的数据,降低重传的需求,提高可靠性和传输效率。
  • 拥塞控制:QUIC内置了拥塞控制机制,可以根据网络状况动态调整数据传输效率,以避免网络拥塞和丢包,提高可靠性。

TCP粘包是怎么解决的?

  • 固定长度的消息。
  • 特殊字符作为边界。
  • 自定义消息结构。

TCP的拥塞控制介绍一下?

拥塞控制目的是避免发送方的数据填满整个网络。

拥塞窗口 cwnd是发送方维护的一个的状态变量,它会根据网络的拥塞程度动态变化的。发送窗口 swnd和接收窗口 rwnd是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。

拥塞窗口 cwnd 变化的规则:

  • 只要网络中没有出现拥塞,cwnd 就会增大;
  • 但网络中出现了拥塞,cwnd 就减少;

发送方没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传,就会认为网络出现了拥塞


慢启动

  • 一点一点的提高发送数据包的数量。
  • 当发送方每收到一个ACK,拥塞窗口cwnd的大小就会加1。
    在这里插入图片描述
    慢启动门限ssthresh
  • 当cwnd<ssthresh时,使用慢启动算法。
  • 当cwnd>=ssthresh时,就会使用拥塞避免算法

拥塞避免算法

  • 每当收到一个ack,cwnd增加1/cwnd。
    在这里插入图片描述
    就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。
    当触发了重传机制,也就进入了拥塞发生算法

拥塞发生
当网路出现拥塞,也就是会发生数据包重传,重传机制主要有两种:

  • 超时重传
  • 快速重传

当发生了超时重传,则就会使用拥塞发生算法。

  • ssthresh设为cwnd/2。
  • cwnd回复为初始值。
    在这里插入图片描述
    接着重新开始慢启动

发生快速重传的拥塞发生算法
还有更好的方式,前面我们讲过快速重传算法。当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。

TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 ssthresh 和 cwnd 变化如下:

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;
  • 进入快速恢复算法

快速恢复
快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。

正如前面所说,进入快速恢复之前,cwnd 和 ssthresh 已被更新了:

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;

然后,进入快速恢复算法如下:

  • 拥塞窗口 cwnd = ssthresh + 3 (3 的意思是确认有 3 个数据包被收到了);
  • 重传丢失的数据包;
  • 如果再收到重复的 ACK,那么 cwnd 增加 1;
  • 如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;
    在这里插入图片描述

描述一下打开百度首页后发生的网络过程?

在这里插入图片描述

  • 解析URL:分析 URL 所需要使用的传输协议和请求的资源路径。如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。如果没有问题,浏览器会检查 URL 中是否出现了非法字符,对非法字符进行转义后在进行下一过程。
  • 缓存判断:浏览器缓存 → 系统缓存(hosts 文件)→ 路由器缓存 → ISP 的 DNS 缓存,如果其中某个缓存存在,直接返回服务器的IP地址。
  • DNS解析:如果缓存未命中,浏览器向本地 DNS 服务器发起请求,最终可能通过根域名服务器、顶级域名服务器(.com)、权威域名服务器逐级查询,直到获取目标域名的 IP 地址。
  • 获取MAC地址:当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址,因为应用层下发数据给传输层,TCP 协议会指定源端口号和目的端口号,然后下发给网络层。网络层会将本机地址作为源地址,获取的 IP 地址作为目的地址。然后将下发给数据链路层,数据链路层的发送需要加入通信双方的 MAC 地址,本机的 MAC 地址作为源 MAC 地址,目的 MAC 地址需要分情况处理。通过将 IP 地址与本机的子网掩码相结合,可以判断是否与请求主机在同一个子网里,如果在同一个子网里,可以使用 ARP 协议获取到目的主机的 MAC 地址,如果不在一个子网里,那么请求应该转发给网关,由它代为转发,此时同样可以通过 ARP 协议来获取网关的 MAC 地址,此时目的主机的 MAC 地址应该为网关的地址。
  • 建立TCP连接:主机将使用目标 IP地址和目标MAC地址发送一个TCP SYN包,请求建立一个TCP连接,然后交给路由器转发,等路由器转到目标服务器后,服务器回复一个SYN-ACK包,确认连接请求。然后,主机发送一个ACK包,确认已收到服务器的确认,然后 TCP 连接建立完成。
  • HTTPS的 TLS 四次握手: 如果使用的是 HTTPS 协议,在通信前还存在 TLS 的四次握手。
  • 发送HTTP请求:连接建立后,浏览器会向服务器发送HTTP请求。请求中包含了用户需要获取的资源的信息,例如网页的URL、请求方法(GET、POST等)等。
  • 服务器处理请求并返回响应: 服务器收到请求后,会根据请求的内容进行相应的处理。例如,如果是请求网页,服务器会读取相应的网页文件,并生成HTTP响应。

网站公告

今日签到

点亮在社区的每一天
去签到