跳至主要內容

计算机网络(core)

holic-x...大约 97 分钟计算机网络计算机网络

计算机网络(core)

学习核心

学习资料

网络传输场景(*)

1.网络分层模型(重要)

介绍一下 OSI 七层协议,各层协议都有哪些?

​ OSI(开放系统互连)模型是由国际标准化组织创建的概念模型,支持各种通信系统使用标准协议进行通信。OSI被视作一种通用计算机网络语言,分成7个抽象层,从上到下分别是应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。网络分层的好处在于各层之间进行解耦,每一层负责处理特定作业并与其上下层进行通信。

​ 各层协议说明:

  • 应用层协议:HTTP、HTTPS
  • 传输层协议:TCP、UDP
  • 网络成协议:IP、ICMP、ARP

​ OSI参考模型只是一种理论模型,实际上因特网中使用的网络模型是TCP/IP网络模型(以四层模型为例),它将OSI参考模型进行了简化,将其中的“应用层、表示层、会话层”统一成“应用层”,将“数据链路层和物理层”统一成“网络接口层”

image-20240826095604272

TCP/IP 网络模型有哪几层?

​ TCP/IP 网络模型 有两种说法(四层 VS 五层),关键核心说明每一层的作用

  • 四层TCP/IP 网络模型:应用层、传输层、网络层、网络接口层

    • 应用层:负责为应用软件提供网络服务(网络层协议有HTTP、HTTPS、DNS协议等)
    • 传输层:负责为应用程序层提供数据传输服务(传输层协议有TCP、UDP,其中TCP是可靠传输协议,UDP是不可靠传输协议)
    • 网络层:负责主机寻址、打包、路由功能(网络层核心协议是IP、ARP、ICMP等)
      • IP协议:负责寻址和路由
      • ARP协议:负责获取MAC地址
      • ICMP协议:负责提供诊断功能并报告错误
    • 网络接口层:负责为网络层提供【链路级别】传输的服务,负责在以太网、WiFi这样的底层网络上发送延时数据包,工作在网卡这个层次,使用MAC地址来标识网络上的设备
  • 五层TCP/IP 网络模型:应用层、传输层、网络层、数据链路层、物理层

image-20240826101513155

IP 协议和 TCP 协议属于哪一层?

​ IP 协议属于网络层(IP:Internet Protocol(网络互连协议),网络之间互连的协议)

​ TCP协议属于传输层(TCP:Transmission Control Protocol(传输控制协议),面向连接的、可靠的、基于字节流的传输层通信协议)

网络为什么要分层?

​ 网络分层的好处在于“解耦”(各层之间相互独立)、“灵活性高”

  • 解耦:各层之间相互独立,每层只需要完成特定的工作,按照指定规则服务于上下层,而不关心上下层的实现。每一层专注于自身的功能实现,可以将一个难以处理的问题分解为若干个容易处理的更小的问题,降低问题的整体复杂度
  • 灵活性高:当某一层发生变化时,只要其与上下层交互的接口关系保持不变,是不会影响相关层的(例如应用层的HTTP协议从1.0升级到2.0版本,并不会对传输层、网络层有影响;同样地,网络层的IP协议从IPV4协议升级为IPV6时也不会影响应用层、传输层)

2.键入网址场景问题(重要)

输入网址后,期间发生了什么?

​ 如果是从“计算机网络”层面回答,则需要相应说明输入网址后涉及到的每一层相关的网络协议的工作原理和作用:

  • 应用层->传输层->网络层->网络接口层
  • HTTP协议/HTTPS协议->DNS协议->TCP->IP协议->ARP协议

image-20240826104948163

​ 用户输入URL后,浏览器会新开一个网络线程发起HTTP请求(解析请求URL,构造HTTP请求报文,发起请求),随后操作系统会进行DNS域名解析将域名解析为实际的IP地址,并与目标服务器建立连接(可能期间会通过负载均衡对应到指定的机器)。由于HTTP是基于TCP传输的,因此在发送HTTP请求前需要进行三次握手,当双方都完成三次握手后,根据应用层协议选择的不同做相应的操作:

  • 如果是HTTP协议:客户端会直接将请求发送给目标服务器
  • 如果是HTTPS协议:客户端还需要和服务端完成TLS(TLS可以理解为SSL的强化扩展)四次握手之后,客户端才会将请求发送给目标服务器

​ 当客户端与服务端真正建立了连接,目标服务器会执行相应的操作并响应返回,随后浏览器接收到响应消息则会相应解析数据并渲染视图,最终呈现给用户

DNS是如何解析的?属于哪一层的协议?

DNS 属于应用层的协议,客户端在进行 DNS 解析之前,会先查看浏览器和操作系统是否有缓存域名对应的IP地址,如果没有就会向本地DNS服务器发出查询请求,接着本地DNS向根DNS发送查询请求,根DNS服务器收到请求后会返回顶级域名服务器的IP 地址,然后本地DNS服务器再向顶级域名服务器发出查询请求,顶级DNS服务器收到请求后会返回权威域名服务器的IP 地址,然后本地DNS服务器再向权威域名服务器发出查询请求,权威域名服务器收到请求后,就会返回域名对应的IP 地址了,最后本地 DNS 服务器返回查询结果给客户端,同时本地域名服务器把返回的结果保存到缓存,以备下一次使用。客户端通过这个IP 地址就可以访问目标Web服务器了

image-20240826112336454

​ 思路分析:DNS 属于应用层的协议,客户端进行DNS解析之前会先查询“缓存”,确认缓存中是否缓存了域名和IP的映射关系,如果没有则会向本地DNS服务器发送查询请求,这个查询请求会依次逐级查询获取信息然后一层层往上,最终得到真正的IP地址并更新缓存,以供下一次使用

DNS域名解析使用的什么协议?

在DNS中,域名解析请求和响应都是基于UDP进行传输的。UDP是一种无连接的传输层协议,它提供了一种简单的传输机制,适用于对实时性要求较高的应用场景。DNS使用UDP协议进行域名解析是因为域名解析通常是短小而频繁的请求,UDP的无连接特性可以减少建立和断开连接的开销,并提高解析的效率

​ UDP对于TCP的缺点是没办法保证数据的可靠传输,针对这个缺陷,可以在应用层实现一个超时重传机制,如果域名解析请求在一定时间内没收到响应,那么就重发域名解析请求。

输入域名如何知道端口的?

​ HTTP 默认端口是 80,HTTPS 默认端口是 443,如果用户指定了端口,比如域名:8080就会使用8080 作为目标端口

  • http://noob.com/,HTTP默认端口是80
  • https://noob.com/,HTTPS默认端口是 443
  • http://noob.com:8080/,指定的端口是 8080

3.网络传输场景问题

如果浏览器没有显示页面有哪些原因?

思路:预先构思一个TCP/IP网络模型的样子(应用层、传输层、网络层、网络接口层),然后根据网络模型一层层排查问题

最直接的办法就是抓包,排查的思路大概有:

(1)先确定是服务端的问题,还是客户端的问题

​ 先在客户端确认浏览器是否可以访问其他网站,如果不可以,说明客户端网络自身的问题,然后检查客户端网络配置(连接wifi正不正常,有没有插网线);如果可以正常其他网页,说明客户端网络是可以正常上网的

(2)如果客户端网络没问题,就抓包确认 DNS 是否解析出了IP 地址,如果没有解析出来,说明域名写错了,如果解析出了IP 地址,抓包确认有没有和服务端建立三次握手:

  • 如果没有成功建立三次握手,需要在服务端通过 ps 确认 server 进程是否启动了,以及通过 netstat 命令确认是否监听了端口

  • 如果能成功建立三次握手,并且发出了 HTTP 请求,但是就是没有显示页面,可以查看服务端返回的响应码:

    • 如果响应码是404,检查输入的url是否正确

    • 如果响应码是500,说明服务器出现问题,需要去服务器排查日志

    • 如果响应码是200,可以在浏览器按F12输出前端控制台,确认前端是否渲染出现异常导致失败

(3)如果客户端网络是正常的,但是访问速度很慢,导致很久才显示出来。可以通过 ping 去确认网络延迟是否正常

  • 如果耗时很严重,可以排查服务器的流量是不是很大,导致超过了带宽上限,产生了丢包的问题。如果网络是正常的,则需进一步排查接口为什么处理这么久(有可能是慢SQL导致)

​ 排查的思路就是一层层进行切入,有没有插网线,网络配置是否正确、DNS有没有解析出IP地址、TCP有没有三次握手、HTTP返回的响应码是什么、前端是否正常渲染、响应速度会不会很慢等

解析

(1)排查是客户端还是服务端的问题,确认网络是否可以正常打通?

(2)确认服务端请求响应状态码(200正常响应,确认响应数据信息),如果是其他的状态码则根据状态码和提示进行定位

(3)如果请求、网络、响应正常,但是由于访问速度很慢导致页面很慢加载完成,需要进一步排查“慢”因素

服务器ping不通但是http能请求成功,会出现这种情况吗?

​ 会的,因为 ping 和 http 使用的协议是不一样的,ping 是基于网络层的 icmp 协议,而 http 是基于传输层的 tcp 协议的,有可能服务器的防火墙禁止 icmp 协议,但是 tcp 协议没有禁止,就会出现服务器 ping 不通,但是http 能请求的现象

客户端 TCP 连接一个不存在的IP地址的服务端会发生什么?(冷门)

分析:区分是否为局域网

​ 如果访问的 IP 地址是局域网内的,客户端的内核在发 arp 请求的时候,广播询问这个目标IP 地址是谁的?由于网络中不存在该目标IP 地址所以没有设备应答客户端的 arp 请求,这时候就会卡在 arp 协议,客户端的 SYN 报文是发送不出去的

​ 如果访问的IP 地址不是局域网的,客户端会先将 SYN 报文发给路由器、然后路由器会继续转发,由于目标 IP 地址是不存在的,该 SYN 报文会在网络中消亡,因此客户端是不会收到对 SYN 报文的确认报文的,随后客户端会触发超时重传,重传 SYN 报文,直到重传的次数达到最大次数后,客户端的连接就会被释放

客户端 TCP 连接一个IP地址存在但是端口不存在的服务端会发生什么?(冷门)

​ 端口不存在的话代表服务端没有监听这个端口,服务端在收到客户端的SYN报文后,服务端会返回RST报文,客户端收到RST报文之后会断开链接

RST是一种TCP/IP协议报文,它的作用是用来重置TCP连接,它通常用于终止TCP连接

客户端 UDP 发送一个IP地址存在但是端口不存在报文会发生什么?(冷门)

​ 服务端会回ICMP报文,报告端口不可达

​ UDP没有RST报文,所以如果端口不存在,此时会在网络层通过ICMP协议报告端口不可达的消息给客户端

应用层(*)

1.HTTP

HTTP协议的特点是什么?

HTTP具有简单、灵活可扩展、无状态等特点,是一种广泛应用于Web通信的协议

基于文本:HTTP的消息是以文本形式传输(HTTP1.1),易于阅读和调试

可扩展性:HTTP协议本身不限制数据的内容和格式,可以通过扩展头部、方法等来支持新的功能

灵活性:HTTP支持不同的数据格式(如HTML、JSON、XML等),适用于多种应用场景

请求应答模式:HTTP 协议使用的是请求-应答通信模式,请求方先发起连接和请求,是主动的,而应答方只有在收到请求后才能答复,是被动的,如果没有请求时不会有任何动作

无状态:HTTP每个请求之间相互独立,服务器不会保留之前请求的状态信息,需要通过其他手段(如Cookies、Session)来维护状态

HTTP 报文格式?怎么分割的?

​ HTTP 的报文格式分为请求行、请求头、请求体三个部分:

  • 请求行:请求或响应的基本信息(例如请求方法、URL、HTTP版本信息等)
  • 请求头:请求头使用key-value形式更详细地说明报文(例如host、connection、content-length字段)
  • 请求体:实际传输的数据,例如文本数据、图片数据

​ 请求行和请求头是通过\r\n分割的,请求头和请求体之间是通过空白行分割的(即两个连续的\r\n

HTTP默认的端口是什么?

​ 端口是TCP协议的概念:

  • 针对HTTP协议,服务端默认监听80端口
  • 针对HTTPS协议,服务端默认监听443端口

HTTP 有什么方法?

​ HTTP/1.1 规定了八种方法:GET、POST、PUT、DELETE、OPTIONS、HEAD、TRACE、CONNECT。结合常用的方法进行说明(例如GET、POST、DELETE、HEAD、PUT等),在实际开发中用GET、POST比较多

  • GET:用于请求从服务器获取资源
  • HEAD:和GET方法类似,也是请求从服务器获取资源,但与GET不同的是,服务器不会返回请求的实体数据,只会传回响应头,也就是获取的是资源的“元信息”
  • POST:用于向服务端提交数据,数据就放在报文的 body 里
  • PUT:和 POST 类似,也可以向服务器提交数据,区别在于POST 是“新增数据”,PUT 是“更新数据”
  • DELETE:用于删除资源

分析一下哪些 HTTP 方法是安全或者幂等的?

分析:理解“安全”、“幂等”的含义,然后解决方法特点进行分析

在 HTTP 协议里,“安全”、“幂等”的概念说明如下:

  • 所谓的“安全”是指请求方法不会“破坏”服务器上的资源,即不会对服务器上的资源造成实质的修改
    • “读”操作是安全的(读取)
    • “写”操作是不安全的(新增、修改、删除)
  • 所谓的“幂等”实际上是一个数学用语,被借用到了 HTTP 协议里,意思是多次执行相同的操作,结果也都是相同的,即多次“幂”后结果“相等”

安全和幂等是两个不同的概念分类,但这些概念分类的前提是开发者必须遵循方法开发规范编写接口逻辑,否则这种分类也是无意义的(例如在GET方法里面写了个删除逻辑,这就脱离问题本质了)

分类说明

  • 安全的方法:GET、HEAD
    • GET、HEAD是只读操作,只要开发者遵循规范要求处理请求,这个操作是安全的
  • 不安全的方法:POST、DELETE、PUT
    • POST、DELETE、PUT这些操作会对服务器资源造成“破坏”(新增、修改、删除),因此是不安全的
  • 幂等的方法:GET、HEAD、DELETE、PUT
    • GET、HEAD是只读操作,不会影响服务器状态,是幂等的;
    • DELETE是删除资源,第一次删除操作执行正常响应提示删除成功,如果再次发送此DELETE请求,则可能会受到HTTP404作为响应,多次删除后效果都是“资源不存在”,这些后面的删除操作并没有更改服务器状态,因此也是幂等的;
    • PUT是修改资源,根据URL找到对应的资源进行更新,多次更新数据的操作结果是确定的(相应替换或更新资源内容),并不会因为多次操作而产生多个不同的资源版本,因此是幂等的
  • 不幂等的方法:POST
    • 多次POST请求会创建多个资源,因此是不幂等的

​ GET 和 HEAD 方法是安全且幂等的,因为它们是只读操作,只要开发者遵循规范要求的去处理请求,无论 GET和 HEAD 操作多少次,服务器上的数据都是安全的。而 POST/PUT/DELETE 这些方法都会增上改服务器上的资源,所以是不安全的。DELETE 和 PUT方法是幂等的,因为 DELETE 是删除资源,多次删除,效果都是资源不存在,所以也是幂等的,另一个 PUT 是更新数据,多次更新数据,结果都一样,所以是幂等的。但是 POST 是不幂等的,因为多次 POST 请求,会创建多个资源,所以不是幂等的。

GET 和 POST 请求的区别?追问:GET 请求一定是安全且幂等的吗?

​ GET:一般用于向服务器请求获取资源

​ POST:一般用于向服务器提交数据

​ 从方法定义以及“安全”、“幂等”的概念核心来分析,GET是只读操作,因此它是安全且幂等的,POST会修改服务器资源,并且多次请求会相应创建多个资源,因此POST是不安全且非幂等的

​ 如果开发者按照既定的规范进行开发,GET请求正常逻辑下是安全且幂等的。如果说开发者忽略方法规范,例如在GET方法中编写了个DELETE操作,就会脱离问题本质,这个操作就会变成不安全的,如果写了个新增操作,那么这个操作就会变成不安全且非幂等

HTTP 有什么状态码?

​ HTTP有相应的状态码分类,按照每个大类进行划分,每个大类下对应相应分类的状态码定义

状态码分类说明常见状态码
1XX提示信息类,协议处理中的一种中间状态101
2XX服务器成功处理了客户端的请求200、204、206
3XX“重定向”提示:客户端请求的资源发生了变动,需要客户端使用新的URL重新发送请求获取资源301、302、304
4XX“客户端”请求异常:客户端发送的报文有误,服务器无法处理400、403、404
5XX“服务端”处理异常:客户端请求报文正确,但是服务器处理时内部发生了错误(属于服务端的错误码)500、501、502、503、504

1XX:提示信息类,协议处理中的一种中间状态(一般用的比较少)

  • 101 Switching Protocols:请求者已要求服务器切换协议,服务器已确认并准备切换。 它的意思是客户端使用 Upgrade 头字段,要求在 HTTP 协议的基础上改成其他的协议继续通信,比如 WebSocket。而如果服务器也同意变更协议,就会发送状态码 101,但这之后的数据传输就不会再使用 HTTP 了。

2XX:服务器成功处理了客户端的请求

  • 200 OK:服务器正常处理并响应(最常见的成功状态码,表示一切正常)
  • 204 No Content:它和200基本相同,区别在于其响应头后没有body数据
  • 206 Partial Content:是HTTP下分块下载或断点续传的基础,在客户端发送“范围请求”要求获取资源的部分数据时出现(和200一样也是响应成功,但区别在于它不是请求资源的全部,而是请求其中一部分)

200、204、206 都是请求成功的常见状态,其中200是最常见的成功状态,而204区别于200的点在于其响应头之后没有body数据,206区别于200的点在于其是分块下载或者断点续传的基础,请求响应的是资源的部分内容而非全部

3XX:“重定向”提示:客户端请求的资源发生了变动,需要客户端使用新的URL重新发送请求获取资源

  • 301 Moved Permanently:永久性的重定向(这种重定向跳转,从严格意义来讲不是服务器跳转,这个“跳”的动作是服务器是通过回传状态码301来下达给客户端的,让客户端完成跳转)
  • 302 Found:临时跳转(例如URL地址A可以向URL地址B上跳转,但这并不是永久性的,在经过一段时间后,URL地址A还可能向URL地址C上跳转)
  • 304 Not Modified:服务器通过返回状态码304可以告诉客户端请求资源成功,但是这个资源不是由服务器提供返回给客户端的,而是客户端本地浏览器缓存中就有的这个资源,因为可以从缓存中获取这个资源,从而节省传输的开销

4XX:“客户端”请求异常:客户端发送的报文有误,服务器无法处理

  • 400 Bad Request:表示请求报文有错误,但具体是数据格式错误、缺少请求头还是 URI 超长它没有明确说,只是一个笼统的错误,客户端看到 400 只会是“一头雾水”不知所措
  • 403 Forbidden:代表请求的服务器资源权限不够,也就是没有权限去访问服务器的资源,或者请求的IP地址被封掉了
  • 404 Not Found:代表服务器上没有该资源,或者说服务器找不到客户端请求的资源,是最常见的请求错误码

5XX:“服务端”处理异常:客户端请求报文正确,但是服务器处理时内部发生了错误(属于服务端的错误码)

  • 500 Internal Server Error:代表服务器程序错误、也就是说请求的网页程序本身报错了。由于现在的浏览器都会对状态码500做一定的处理,所以在一般情况下会返回一个定制的错误页面
  • 501 Not lmplemented:服务器不具备完成请求的功能(例如,服务器无法识别请求方法时可能会返回此代码)
  • 502 Bad Gateway: 通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误
  • 503 Service Unavailable:表示服务器当前很忙,暂时无法响应客户端(例如上网时有时候遇到的“网络服务正忙,请稍后重试”的提示信息)
  • 504 Gateway Timeout:服务器作为网关或代理,但是没有及时从上游服务器收到请求

什么情况下会出现502错误码呢?

​ 502 (Bad Gateway) 状态代码表示服务器在充当网关或代理时,在尝试满足请求时从它访问的入站服务器接收到无效响应。

​ 简单理解就是,502其实是由网关代理(nginx)发出的,是因为网关代理把客户端的请求转发给了服务端,但服务端却发出了无效响应,而这里的无效响应,一般是指TCP的RST报文或四次挥手的FIN报文。

502是网关代理无法从应用服务器获取响应而返回给客户端的错误码信息提示

如果客户端访问服务器是通过nginx反向代理到应用服务器,那么如果应用服务器出现故障,导致nginx无法从应用服务器获取到响应,则nginx就会返回502错误码给客户端(例如现实业务场景中流水线中重新部署应用失败,通过前端访问nginx则会提示502(Bad Gateway))

有个服务出现了504,分析下这个服务是出了什么问题?

504是网关请求超时错误

​ 504是网关超时错误,通常是nginx将请求代理到后端应用时,后端应用没有在规定的时间返回数据,需要开发检查下应用那块有什么耗时的操作,比如是否出现了sgl 慢查询、接口是否发生死循环、死锁等问题,然后后端服务器系统负载高不高等

重定向是哪一类状态码?临时重定向和永久重定向有什么区别?

​ 3XX类状态码是“重定向”状态码

  • 301 是永久重定向(浏览器会记住):这种重定向并不是服务器完成跳转,而是返回状态码给客户端,由客户端进行跳转

    • 当访问a.com被永久重定向到b.com浏览器会记忆重定向后的URL地址,下次访问a.com时浏览器会直接跳转到b.com而不会再请求a.com
  • 304 是临时重定向(浏览器不会记住):

    • 当访问a.com被临时重定向到b.com浏览器并不会记忆重定向后的URL地址,下次访问a.com时浏览器还是会先请求a.com然后再跳转到b.com
    • 临时重定向的概念在于这次可能是a.com=>b.com下次可能就是a.com=>c.com,因此浏览器也没有必要记住

HTTP是长连接还是短连接?

​ HTTP 1.0 虽然支持长连接,但是默认的连接行为是短连接。从HTTP 1.1 版本之后,都是默认长连接。HTTP 长连接的优势是减少TCP连接资源的开销

​ 长连接相关的配置:请求头中的Connection配置:

  • 如果要开启长连接:Connection: Keep-Alive
  • 如果要关闭长连接:Connection: close

HTTP长连接和短连接的区别? 长连接的优势?

短连接:每次通信请求都需要建立新的连接,请求完成后立即关闭连接。这样每次请求都需要建立连接和释放连接,会增加通信开销和延迟

长连接:在通信过程中保持连接的持续性,多次请求可以共享同一个连接。在长连接中,客户端和服务器建立连接后可以进行多次请求和响应,减少了连接建立和释放的开销,提高了通信效率

长连接的好处在于可以在一次TCP连接中发送和响应多个HTTP请求,减少TCP连接资源创建和断开的开销

image-20240826161640033

HTTP 版本升级迭代的对比分析?

HTTP/1.0 和 HTTP/1.1 的区别?

  • 长连接HTTP/1.1默认的连接行为是长连接,而HTTP/1.0虽然也支持长连接,但是默认是使用短连接
  • 请求管道化HTTP/1.1 支持请求管道传输(pipline)的方式,HTTP/1.0不支持这个模式,HTTP/1.0 请求和响应必须是串行的,当一个请求和它响应完成之后,才能发送下一个请求,而 HTTP/1.1 由于支持管道传输方式,因此可以并发发送HTTP请求,能够提高HTTP请求的效率,但是HTTP响应还是得按顺序响应,只有HTTP/2.0 实现了 HTTP 请求和响应的并发传输的能力。
  • host 字段HTTP/1.0 没有 host 字段,HTTP/1.0 新增了 host 字段,通过Host头部字段,一个物理服务器可以承载多个域名或站点。
HTTP/1.1 对比 HTTP/1.0HTTP/1.1HTTP/1.0
长连接默认是长连接默认是短连接,也支持长连接(Connection:Keep-Alive
请求管道化支持并发:新增对请求管道化的支持,支持并发发送HTTP请求,提高请求效率,但是响应还是按顺序响应串行:请求和响应是串行的,只有一个请求和响应完成后才能发现下一个请求
host字段新增host字段,一个物理服务器可以承载多个域名或站点

HTTP/1.1 和 HTTP/2.0 的区别?

HTTP/2 相比 HTTP/1.1 性能上的改进:

  • 并发传输(Stream的引入)HTTP/2.0中引入Stream优化请求和响应的并发操作
    • HTTP/1.1虽然支持请求管道化(支持请求并发传输,但不支持响应并发传输),可以并发传输HTTP请求,但是无法做到HTTP响应的并发传输(响应还是按照一定顺序的)
    • HTTP/2.0中引入Stream的概念(支持请求和响应的并发传输),不同的HTTP请求和响应用不同的Stream区分,多个Stream复用一条TCP连接,只需要一条连接就能达到并发传输的效果
  • 报文改进(头部压缩+二进制格式)HTTP/2.0在报文格式上做了改进,使用HPACK算法压缩了HTTP头部,并将原纯文本的格式改为二进制格式,提高数据传输效率
  • 服务器主动推送资源HTTP/2.0支持服务器主动推送资源(例如客户端从服务器上获取HTML文件时,可能页面渲染还需其他CSS/JS/IMAGE资源,此时服务器可以主动推送资源文件,减少消息传递的次数)

HTTP/2.0 和 HTTP/3.0 的区别?

分析:结合HTTP/2.0的缺陷进行优化分析

  • 传输层协议不同HTTP/2.0HTTP/3.0最大的区别在于传输层使用的协议不同:

    • HTTP/2.0存在TCP队头阻塞问题,HTTP/3.0将传输层协议从TCP协议切换到UDP协议,并在这个基础上实现了一个可靠传输的QUIC协议,优化队头阻塞问题
  • HTTP/3.0连接建立更高效

    • HTTP/2.0建立连接时需 3次 TCP 握手+ TLS 四次握手
    • HTTP3.0 的 QUIC 协议只需要3次握手就能完成连接建立+TLS握手建立
  • HTTP/3.0在网络环境切换的过程中,可以不需要重新建立连接:在应用层通过连接ID唯一确认连接,就算网络切换也不影响原本的连接

    • 以往 HTTP 都是基于 TCP 协议进行传输,TCP 是根据四元组信息唯一确认一条连接,如果四元组信息某一个信息发生变化了,这时候就需要断开连接,重新建立连接、比如4G网络切换到 WIFI网络的时候,所有的 TCP 连接都需要重新建立
    • 而 HTTP/3.0 是在应用层通过连接ID 来唯一确认连接的,即使网络发生切换,也不会影响原本的连接,消除重连的成本

HTTP是无状态的吗?

HTTP 是无状态的,一般会通过 Cookie、Session、Token这些机制来维护用户的状态

​ HTTP是无状态的(意味着每个请求都是独立的),服务器不会在多个请求之间保留关于客户端状态的信息。在每个HTTP请求中,服务器不会记住之前的请求或会话状态,因此每个请求都是相互独立的,因此服务器不知道请求两次之间是否是同一个用户。”无状态“会带来用户资源切换混乱问题,用户登录后,切换到其他界面进行操作,服务器端是无法判断是哪个用户登录的,每次进行页面跳转的时候,得重新登录

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

HTTP 用户后续的操作,服务端如何知道属于同一个用户?追问:如果服务端是一个集群机器?

HTTP 虽然是无状态的,但是可以通过引入Cookies、Session、Token等机制来跟踪用户状态。如果采用的是session方案(用户登录信息是存储在服务端的),如果服务端是一个集群机器,可以使用一台Redis保存session数据,进而达到共享session的效果。为了避免单点故障问题,还可引入Redis集群方案来避免单点问题(但这种方案的成本可能有点高)

​ 如果不采用session,可以改用JWT方案,JWT的状态信息是保存在客户端的,服务端不再保存状态信息,天然适合分布式系统

Cookie、Session、JWT 相关(认证、授权相关)

(1)认证(Authentication)和授权(Authorization)的区别是什么?

​ 认证:你是谁? 授权:你有权利干什么? 认证+授权结合使用,保护系统安全性

  • 认证:验证身份的凭据(身份/用户验证),通过这个凭据让系统知道你是谁?
  • 授权:发生在认证之后,掌管用户访问系统的权限。只有特定的角色才能访问特定资源,例如只有admin才能对特定数据进行新增、删除、修改操作

(2)什么是Cookie?什么是Session?Cookie和Session的区别?

​ Cookie 和 Session都是⽤来跟踪浏览器⽤户身份的会话⽅式,但是两者的应⽤场景不太⼀样。

​ Cookies是某些⽹站为了辨别⽤户身份⽽储存在⽤户本地终端上的数据(通常经过加密)。 Cookie 存放在客户端,⼀般⽤来保存⽤户信息;Session 的主要作⽤就是通过服务端记录⽤户的状态

Cookie 的⼀些应⽤案例:

【1】在 Cookie 中保存已经登录过的⽤户信息,下次访问⽹站的时候⻚⾯可以⾃动填充登录的⼀些基本信息。除此之外,Cookie 还能保存⽤户⾸选项,主题和其他设置信息

【2】使⽤Cookie 保存 session 或者 token ,向后端发送请求的时候带上 Cookie,让后端取到session或者token。以此记录⽤户当前的状态,因为 HTTP 协议是⽆状态的

【3】Cookie 还可以⽤来记录和分析⽤户⾏为。例如在⽹上购物的时候,因为HTTP协议是没有状态的,如果服务器想要获取你在某个⻚⾯的停留状态或者看了哪些商品,⼀种常⽤的实现⽅式就是将这些信息存放在Cookie

​ 在服务器端使用Cookie,可以借助Cookie类进行操作,也可以借助Spring框架的**@CookieValue注解**获取到特定的cookie值

​ Session 的主要作⽤就是通过服务端记录⽤户的状态。典型的场景是购物⻋,当要添加商品到购物⻋的时候,系统不知道是哪个⽤户操作的,因为 HTTP 协议是⽆状态的。服务端给特定的⽤户创建特定的 Session 之后就可以标识这个⽤户并且跟踪这个⽤户

​ Cookie数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说Session安全性更高,如果使用Cookie的一些敏感信息不要写入Cookie中,最好能将Cookie信息加密然后使用到的时候再去服务器端解密。

(3)如何用Session进行身份验证?

​ 一般都是通过特定的SessionID来标记特定的用户(SessionID一般存放在Redis中)

​ 登录验证:⽤户成功登陆系统,服务器返回给客户端具有SessionID的Cookie,当前端向后端发起请求的时候会把 SessionID 带上,让后端知道当前用户的身份状态

image-20240826171543201

服务端用session验证用户身份信息的过程

【1】用户输入登录信息请求登录系统

【2】服务器接收请求验证用户登录信息,验证通过随后创建一个session并将其存储在服务端

【3】服务器返回这个session对应的SessionID给前端,前端将其写入Cookie

【4】后续的每个请求,前端都会带上这个Cookie中存储的sessionID值用于身份校验(确认用户本地登录是否失效)

【5】服务器接收每个请求就会相应校验SessionID是否有效,验证用户身份、限制用户行为

​ 使用session的时候要确认客户端开启了Cookie用于存储SessionID、并注意session的过期时间

扩展问题:如果没有Cookie、Session还能用吗?如果禁用 Cookie,怎么实现 Session?

​ 因为Cookie只是本地SessionID的一种保存方案,如果采用了这种方式存储却禁用Cookie的话,则session无法正常工作。因为禁用Cookies代表响应头无法使用Set-Cookie字段、请求头无法使用Cookies字段,此时则无法通过HTTP Cookie传输SessionID。

​ 但可以采取另一种方案将SessionID带到请求URL中,例如通过URL传递:http://localhost:8080/getMyName?SessionID=xxx,但是基于这种方案安全性尤其差,需考虑加密问题

(4)什么是Token?什么是JWT?如何基于Token进行身份验证?

​ 基于上述用Session鉴别用户身份信息这种方式,需要确保Session信息服务器的可用性、以及Cookie的开启(部分移动端不支持Cookie),具备一定的不足。

​ 此处引入Token、JWT(JSON Web Token)概念,只需要在客户端保存服务器返回给客户的Token即可,基于这种方式服务端不需要保存session数据,而是通过Token令牌来校验用户身份

JWT本质上为一段签名的JSON格式的数据,由于带有签名,接收者可以验证它的真实性

JWT组成说明
Header描述JWT的元数据,定义生成签名的算法以及Token类型
Payload(负载)用于存放实际需要传递的数据
Signature(签名)服务器通过Header、Payload、一个秘钥(secret)生成签名(使用Header指定的签名算法生成)
image-20240826171941382

JWT验证身份信息流程

【1】⽤户向服务器发送⽤户名和密码⽤于登陆系统

【2】服务器验证登录信息,随后生成JWT(通过Header、Payload和secret按照指定算法创建令牌Token)并将其发送给客户端

【3】客户端接收后将Token保存到本地(Cookie、localStorage),在之后的每次向后端发请求都在Header中携带这个Token令牌

【4】服务端检查请求发送的JWT 并从中获取⽤户相关信息,进而控制用户访问权限

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

​ JWT包含身份验证和会话信息,不依赖于服务端存储会话信息,客户端和服务端之间交互通过token进行鉴权,进而解决了集群部署中的身份验证和会话管理问题。

JWT 有什么缺点?

令牌难以主动失效、需考虑防盗用问题

​ JWT的最大缺点是令牌难以主动失效,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器搞了额外的逻辑、比如设计一个“黑名单”的额外的逻辑,用来把要主动失效的令牌集中存储起来,然后,每次使用 JWT 进行请求的话都会先判断这个 JWT 是否存在于黑名单中。

​ JWT 要防止盗用的问题,因为 JWT 包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限,为了减少盗用,JWT的有效期应该设置得比较短,而且不应该使用 HTTP 协议明码传输,要使用 HTTPS协议传输

(5)Cookie、Session 和 Token 有什么区别?

从存储位置、数据安全性、跨域支持、状态管理这几个方面进行分析

​ Cookie、Session 和 Token 通常都是用来保存用户登录信息的技术,但三者有很大的区别,简单来说三者的适用场景说明如下:

  • Cookie 适用于简单的状态管理;Session 适用于需要保护用户敏感信息的场景;而 Token 适用于状态无关的身份验证和授权
CookieSessionToken
存储位置客户端存储服务端存储(一般存储在服务器的内存或数据库中)客户端存储,通常以加密的方式存储在客户端的sessionStorage、localStorage中
数据安全性Cookie存储在客户端存在数据安全问题,需对敏感信息进行处理客户端和服务端直接通过sessionID进行交互,避免敏感信息直接暴露Token通常使用加密算法生成,有效期较短且单向不可逆,安全性较高
跨域支持不支持由于Session机制一般和Cookie搭配使用,因此默认情况下也不支持Token是无状态的,不同域名的Token信息传输通常是不受影响的
状态管理应用程序通过在客户端存储临时数据,用于实现状态管理服务端记录用户状态的方式,服务端为每个会话分配一个唯一的sessionID,将其与用户状态进行关联Token是一种认证和授权的机制,通常表示用户的身份信息和权限信息
(6)为什么Cookie无法避免CSRF攻击而Token可以?

​ CSRF(Cross Site Request Forgery)⼀般被翻译为跨站请求伪造(简单来说⽤用户的身份去发送⼀些对用户不友好的请求)

​ 通过上述session存储用户信息的方式,攻击者让用户误点链接,随后从Cookie中拿到对应的sessionID信息,随后伪装用户向网站发送请求,以达到攻击的目的

​ 如果采用token的方式,用户在登录成功后将Token存储到local stroage中,前端通过某种方式将Token放在请求中(例如放在Header指定字段中)。即使此时用户不小心点击了某个非法链接,但是这个非法请求无法携带token(或者说攻击者不明确具体身份校验的规则,Token的内容),因此服务器验证这个请求是非法的

​ 但需注意这两种方式都无法避免跨站脚本攻击(Cross Site Scripting)XSS,在这个模式下攻击者会用各种方式将恶意代码注入到其他用户页面,通过脚本盗用信息等。

(7)OAuth2.0 VS 单点登录SSO

​ OAuth 是⼀个⾏业的标准授权协议,主要⽤来授权第三⽅应⽤获取有限的权限(OAuth2.0是对OAuth1.0的完全重新设计)

​ OAuth2.0最常用的场景是用于第三方登录、支付场景(微信支付、支付宝支付)、开发平台(微信开放平台、阿里开放平台),它是一种授权机制,为第三方应用颁发一个有时序性的令牌Token,让第三方应用可以通过该令牌访问相关资源

​ SSO(Single Sign On)即单点登录,⽤户登陆多个⼦系统的其中⼀个就有权访问与其相关的其他系统。例如在登陆了京东⾦融之后,同时也成功登陆京东的京东超市、京东家电等⼦系统。(类似的淘宝体系)

什么是跨域?什么情况下会发生跨域请求?

​ ”同源策略“问题:

​ 当一个网页去尝试访问不同源的资源的时候,就意味着发生了跨域请求,只要域名、协议、端口这三个信息任意一个不同,都认为是不同源的URL

​ 跨域请求在浏览器上是不被允许的,只要在浏览器上发生跨域请求操作时,浏览器就会自动抛出的错误如果想绕过这个限制,可以用跨域资源共享(CORS)技术,实现的方式是服务器需要在响应头上添加 Access-Control-Allow-Origin 的字段,设置需要放行的域名,浏览器识别到了,才能放行该请求

RestFul 是什么?RestFul 请求的 URL 有什么特点?

​ Restful 是一种 API 接口设计规范,用 URL 定位资源,用HTTP 方法表示接口的动作,用 HTTP 状态码表示接口处理的情况

RestFul风格的 HTTP 接口可以通过 URL 就能判定这个接口是做什么的。比如:

  • /articles POST:代表新增一个文章
  • /articles GET:代表获取全部文章,有可能后边带参数进行一些过滤查询或分页
  • /articles/1 GET:代表获取 id 为1这篇文章
  • /articles/1 PUT:代表更新id为1的文章,请求体可能会带一些更新内容
  • /articles/1 DELETE:代表删除id为1的文章

2.HTTPS

HTTP 和 HTTPS 有什么区别?

核心:安全性、建立连接、端口号、证书 这几个方向切入

区别HTTPHTTPS
安全性明文传输协议,数据在传输过程中不加密,容易被窃听和篡改使用SSL/TLS协议对数据进行加密
建立连接TCP三次握手之后便可进行HTTP的报文传输在TCP三次握手之后需进行SSL/TLS的握手过程,才能进入加密报文传输
端口号默认端口是80默认端口是443
证书/需使用数字证书验证服务器身份,以确保数据传输的安全性

了解过哪些加密算法?各自有哪些算法?

核心:对称加密算法、非对称加密算法、哈希算法

​ 在 HTTPS 协议里,对称加密算法和非对称加密算法这两种算法都会用到

对称 VS 非对称:对称加密算法就是用一个密钥进行加解密(比如 AES 算法),非对称加密则是有2个密钥,分别是公钥和私钥(比如RSA算法

哈希算法主要用过 MD5 算法,哈希算法是一种单向算法,用户可以通过哈希算法对目标信息生成一段特定长度的唯一的哈希值,却不能通过这个哈希值重新获得目标信息,所以用于数据完整性校验方面

区别(加解密速度、密钥传输)、适用场景

  • 对称加密算法(AES、DES):加解密都是对同一个密钥进行操作,加解密过程速度较快,适用于大量数据的加解密
  • 非对称加密算法(RSA、ECC):加解密过程涉及两个密钥(公钥和私钥),加解密过程速度较慢(需要更复杂的数学运算),适用于少量数据的加解密,例如密钥交换和数字签名等场景
    • 公钥可以任意分发,但私钥必须保密(例如A给B发私密消息,A使用B的公钥对消息加密,随后发送给B,B接收后使用自己的私钥进行解密得到原始消息)
  • 哈希算法:适用于数据完整性校验方面

HTTPS 的混合加密方式

​ 在 HTTPS 协议里,涉及对称加密算法和非对称加密算法:

  • 通信建立前采用非对称加密的方式交换「对称密钥」,后续就不再使用非对称加密
  • 通信过程中全部使用「对称密钥」的方式加密明文数据

假设有一个文件,大小未知,现在要把它上传到云端,该使用对称加密还是非对称加密算法?

此处选择对称加密算法,它的运算速度比非对称加密算法更快,适用于数据量大的场景

​ 对称加密比非对称加密快的原因:

​ 对称加密主要的运算是位运算,速度非常快,如果使用硬件计算,速度会更快,但是非对称加密计算一般都比较复杂,比如 RSA,它里面涉及到大数乘法、大数模等等运算。除了慢,可能还有一个缺点就是需要更多的位数,相同强度的对称密钥要比非对称密钥短。对称密钥一般都128位、256位,而RSA-般要2048位,不过椭圆曲线的会短一点。

HTTPS 建立过程是怎么样的?

核心:结合HTTP的连接建立过程进一步分析理解

​ 首先客户端要和服务端先进行 TCP 三次握手建立 TCP 连接。接下来,会进行 TLS 四次握手:

  • 第一次 TLS 握手:客户端首先会发一个 Client Hello 消息,消息里面有客户端使用的 TLS 版本号、支持的密码套件列表、客户端生成的随机数
  • 第二次 TLS 握手
    • 当服务端收到客户端的消息后,会返回 Server Hello 消息给的客户端,消息里面有服务器确认的 TLS 版本号、密码套件、服务端生成的随机数。
    • 服务端为了证明自己的身份,会发送 ServerCertificate 给客户端,这个消息里含有数字证书
    • 随后,服务端发了 Server Hello Done 消息,目的是告诉客户端,我已经把该给你的东西都给你了,本次握手完毕
  • 校验证书:客户端收到服务端的数字证书的时候,会对校验服务端的证书,如果证书是合法的,客户端会用CA机构的公钥解密数字证书拿到服务端的公钥
  • 第三次 TLS 握手:客户端再次生成一个随机数,用服务端的公钥加密后,通过 Client Key Exchange 消息传给服务端。服务端收到后,用服务端的私钥解密得到客户端的第二个随机数。到这里,服务端和客户端双方都有3个随机数,双方根据已经得到的三个随机数,会根据算法生成对称密钥。生成完对称密钥后,客户端会发一个消息告诉服务端开始使用对称加密方式发送消息,并且还会对之前所有发送的数据做个摘要,再用对称加密加密一下,让服务器做个验证,验证对称密钥是否可用,以及之前握手信息是否有被中途篡改
  • 第四次 TLS 握手:服务器也是同样的操作,发送消息告诉客户端开始用对称加密方式发送消息,并且也会对数据做个摘要,并用对称密钥加密一下,让客户端做个校验,如果双方都验证加密和解密没问题,那么TLS 四次握手正式完成了
  • 加解密HTTP请求和响应:最后,就用对称密钥加解密 HTTP 请求和响应

为什么需要三个随机数?

​ 因为计算机生成的随机数其实是一个伪随机,那么只用一个随机数来生成的对称密钥很容易就被破解了,用三个伪随机数就十分接近随机了,这样称密钥破解的难度都变高了。

计算机生成的随机数是伪随机概念,多个随机数的目的是为了让对称密钥的随机性更高,不容易被算到

一次HTTPS需要几次RTT(就是几个来回)?

​ RTT是往返的延时,HTTP是四次握手即代表了2次往返(即2次RTT)

了解业界现在有一个RTT建立HTTPS连接的方案吗?

HTTPS 过程进行了多少次非对称加密?多少次对称加密?

分析:从HTTPS握手之前、握手期间、握手之后进行分析

  • 还未 HTTPS 握手之前

    • 服务端在向 CA 机构注册证书的时候,CA 机构会用 CA 私钥会对服务端的公钥进行签名,形成数字证书,这里涉及了1次非对称加密
  • HTTPS 握手期间

    • 客户端会用服务端的公钥加密随机数,服务端再用私钥解密,这里涉及了1次非对称加密
    • 客户端和服务端生成对称密钥之后,都需要对之前握手的数据做个摘要,并用对称密钥加密一下,这个过程客户端和操作都会涉及到,所以 HTTPS 握手期间用了2次对称加密,客户端和服务端各做了一次
  • HTTPS 握手完成之后

    • HTTPS 数据传输期间都是用对称密钥进行加密和解密

SSL握手流程为什么要使用非对称加密?

​ 非对称加密的过程涉及两个密钥的使用,它的安全性相对较高,可以避免报文在传输过程中被篡改。

​ 如果使用对称加密算法,一旦密钥被窃取,这个报文就很容易被破解。对于非对称加密而言,就算拿到公钥和私钥是配套的,就算拿到公钥,也很难直接通过公钥进行破解,只有真正拿着私钥的客户端才能解密成功

为什么 HTTPS 不用非对称加密算法加密 HTTP 报文?

​ 非对称加密算法虽然安全性高,但是它的计算复杂度较对称加密算法也相对较高,一般不适用于大数据量的频繁的加解密操作。而HTTP报文通常包含大量的数据,如果直接使用非对称加密算法对整个报文进行加解密,则可能导致性能下降和延迟增加问题

HTTPS 会对 URL 加密吗?

​ URL 是属于 HTTP 报文头部的信息,HTTPS 会对整个 HTTP 报文都会加密,所以 HTTPS 是会对 URL 加密的。

​ 但从浏览器地址栏显示来看是”明文“的,是因为浏览器已经自行解密好了

CA 机构如何验证server身份?

​ 服务端在向CA机构申请证书的时候,CA机构会通过自己的私钥对服务器的一些信息进行数字签名,然后在HTTPS握手阶段的时候,服务端会发送证书给客户端来验证,客户端实际上已经内置了CA机构的公钥,那么就用这个公钥来验证服务端的数字证书是否是可信的。

证书是绿色的是什么意思?

​ 代表网站是可信的,浏览器在 HTTPS 握手阶段会对网站服务器下发的证书进行校验,如果校验成功,代表网站的身份的可信的,是被 CA 机构认证过的。

自己随便编一个证书可以吗?需要去什么地方注册?

​ 不可以。浏览器在校验这个证书的时候,会认为是非法的证书,这时候浏览器会显示访问的网站是不可信。得去 CA 机构申请证书,浏览器才会认为是合法的证书,这样才能正常的访问网站的内容

3.RPC

RPC的作用是什么?

​ RPC(Remote Procedure Call,远程过程调用)主要运用于微服务之间的通信,它的作用是帮助开发者屏蔽网络编程细节,可以像是调用本地方法(调用同一个项目中的方法)一样调用远程方法,让开发者更专注于业务逻辑,而无需关注底层网络通信的细节。

为什么有HTTP协议了?还要用RPC?

​ HTTP 和 RPC 其实是两个维度的东西, HTTP 指的是通信协议,而 RPC 则是远程调用。RPC 的通信可以用 HTTP 协议,也可以自定义协议,是不做约束的。

​ 用 HTTP 传输数据会有比较多的信息,比如头部有各种字段信息,数据载体则一般是用json 格式。而 RPC 因为它定制化程度更高,可以采用体积更小的protobuf或其他序列化协议去保存结构体数据,同时也不需要像HTTP那样考虑各种浏览器行为(比如302重定向跳转啥的),因此性能也会更好一些,这也是在公司内部微服务中抛弃HTTP,选择使用RPC的最主要原因

4.Nginx

Nginx位于七层网络结构中的哪一层?

​ nginx 是七层负载均衡

Nginx有哪些负载均衡算法?

Nginx支持的负载均衡算法包括:

  • 轮询按照顺序依次将请求分配给后端服务器
    • 最简单的负载均衡算法,但是存在无法处理某个节点变慢或者客户端操作有连续性的情况
  • 加权轮询按照权重分配请求给后端服务器,权重越高的服务器获得更多的请求
    • 适用于后端服务器性能不同的场景,可以根据服务器权重分配请求,提高高性能服务器的利用率
  • IP哈希根据客户端IP地址的哈希值来确定分配请求的后端服务器
    • 适用于需要保持同一客户端的请求始终发送到同一台后端服务器的场景(如会话保持)
  • URL哈希按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率
  • 最短响应时间按照后端服务器的响应时间来分配请求,响应时间短的优先分配
    • 适用于后端服务器性能不均的场景,能够将请求发送到响应时间快的服务器,实现负载均衡
  • 最短连接:新请求会发送到并发连接最少的服务节点

什么是反向代理?什么是正向代理?

​ 正向代理代理的是客户端这一方,其真实客户端对服务器不可见

​ 反向代理代理的是服务器这一方,其真实服务器对客户端不可见,可以通过负载均衡策略,将请求转发的不同的服务器上

传输层(*)

1.TCP 三次握手

TCP 头部有哪些字段?

image-20240827072032592

说明TCP头部核心字段:序列号、确认号、源端口号、目的端口号、标记位(SYN、ACK、FIN、RST)、头部长度、窗口大小、可扩展的选项等

  • 序列号和确认号都是32位大小
    • 序列号可以保证数据的有序性(接收方会按照发送方顺序发送的数据来组装有序的数据)
    • 确认号可以保证数据的可靠性(当发送方已发送的数据,超过一段时间没受到确认报文就会重传报文)
  • 源端口号和目的端口号是16位大小,端口的作用是标识TCP连接是哪个进程的
    • 源端口号是发送方使用的端口号
    • 目的端口号是接收方使用的端口号

控制位(标记位)补充说明

  • URG:紧急指针标志(0-忽略;1-有效),紧急指针设置为有效则意味着该报文应该优先传输
  • ACK(Acknowledge character):确认序号标志(0-报文中不含确认信息;1-有效),携带ACK标识的TCP报文段被称为确认报文段
  • RST:重置连接标志(用于重置由于主机崩溃或其他原因而出现错误的连接,或者用于拒绝非法的报文段和拒绝连接请求),携带RST标志的TCP报文段为复位报文段
  • SYN(Synchronize Sequence Numbers,同步序列不编号):建立连接标志(TCP/IP建立连接时使用的握手信号,表示请求建立一个连接),称携带SYN标志的TCP报文段为同步报文段
  • FIN:FINISH标志(用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流),携带FIN标志的TCP报文段为结束报文段
  • PSH:PUSH标志(为1表示带有push标志的数据,指示接收方在接收到该报文段以后,应优先将这个报文段交给应用程序,而不是在缓冲区排队)

说一下 TCP 三次握手的过程

image-20240827075310329

三次握手:建立一个TCP连接需要三次握手,双方确认彼此收发功能是否正常

SYN:同步序列编号(Synchronize Sequence Numbers),TCP/IP建立连接时使用的握手信号

ACK:(Acknowledge character)确认字符,由接收方发送给发送站的传输类控制字符,用于确认接收无误

  • ⼀次握⼿:客户端 =》发送带有 SYN 标志的数据包 =》服务端
  • ⼆次握⼿:服务端 =》发送带有 SYN/ACK 标志的数据包 =》客户端
  • 三次握⼿:客户端 =》发送带有带有 ACK 标志的数据包 =》服务端

​ 为什么需要三次握手:为了建立可靠的通信信道,双方确认自己与对方的发送和接受是正常的

为什么需要三次握手?两次不行吗?

三次握手机制的设定:

  • 有效防止历史连接的建立(双方彼此确认)
    • 假设发送方要发送序号为100的SYN报文,而网络中残留序号为90的SYN报文,如果第1次握手就建立连接,那么可能出现重复建立连接的问题。如果是基于3次握手的机制,第1次握手发送方发送SYN(100),接收方接收后响应第2次握手发送SYN(101),发送方预期接收SYN(101)并发送ACK确认进行第3次握手。如果在这个过程中接收方先处理了SYN(90),那么它在第2次握手的过程中发送方发现传过来的SYN(91)并不是预期的内容,于是就会断开连接并且返回RST给接收方,接收方接收到RST后也就会断开连接,进而避免历史连接的重复建立
  • 确认客户端和服务端是否同时具备收发消息的能力
    • 两次握手只能证明发送方具有发送能力、接收方具有接收和发送能力,而无法确认发送方也具有接收能力,因此需要经过第三次握手来进一步验证

​ PS:理解”为什么网络中会残留SYN报文“,基于异常场景考虑,假设客户端发送了一个SYN(seq=90)的报文后就宕机了,而且这个SYN报文还被网络阻塞了,导致服务端并没有收到。当客户端重启恢复后又重新向服务端发送了SYN(seq=100)报文

image-20240827080623259

如果第一次握手丢包,会发生什么?

​ 如果第1次握手丢包,达到超时重传的时机则会触发超时重传机制(重传SNY报文)。当重传次数达到最大次数,发送方还是没有收到第2次握手(SYN-ACK报文)的话,则客户端会断开连接

如果第二次握手丢包,会发生什么?

理解第2次握手的目的:发送SYN-ACK报文,此处有两层含义

  • 第2次握手中的ACK:是对客户端第1次握手的ACK确认报文
  • 第2次握手中的SYN:是服务端发起建立TCP连接的报文

​ 如果说在第2次握手过程中丢包,那么可以结合这两点进行分析:

  • 由于丢了"ACK":客户端长时间没有收到ACK则会在一定时机触发"重传机制"(重传SYN报文)
  • 由于丢了"SYN":服务端无法进行第3次次握手,因此在一定时机触发了服务器端的"重传机制"(重传SYN-ACK报文)

如果第三次握手丢包,会发生什么?

理解第3次握手的目的:发送ACK报文

  • 第3次握手中的ACK:是对服务端第2次握手中发送的SYN报文的确认

​ 如果说在第3次握手过程中丢包,那么服务端接收不到ACK就无法完成第3次握手,则会触发服务器端的”重传机制“(重传SYN-ACK报文)

TCP 的半连接队列和全连接队列

在TCP三次握手的时候,Linux内核会维护两个队列:

  • 半连接队列(SYN队列):服务端收到客户端发起的 SYN 请求后,内核会把未完成握手的连接存储到半连接队列,等待完成三次握手后转移到全连接队列
  • 全连接队列(accept队列):服务端收到第三次握手的 ACK后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到全连接队列,等待进程调用 accept 函数时把连接取出来
image-20240827085351518

2.TCP 四次挥手

TCP 四次挥手的过程

四次挥手:断开⼀个 TCP 连接则需要“四次挥⼿”,是为了确认双方彼此没有数据要接收或发送,双方确认连接释放的通知,关闭TCP连接

FIN:结束信号

  • 第1次挥手:客户端-发送⼀个 FIN,⽤来关闭客户端到服务器的数据传送

  • 第2次挥手:服务器-收到这个 FIN,它发回⼀个 ACK,确认序号为收到的序号加1 (和 SYN ⼀样,⼀个FIN 将占⽤⼀个序号)

  • 第3次挥手:服务器-关闭与客户端的连接,发送⼀个FIN给客户端

  • 第4次挥手:客户端-发回 ACK 报⽂确认,并将确认序号设置为收到序号加1

​ 为什么需要四次挥手:任何⼀⽅都可以在数据传送结束后发出连接释放的通知,待对⽅确认后进⼊半关闭状态。当另⼀⽅也没有数据再发送的时候,则发出连接释放通知,对⽅确认后就完全关闭了TCP连接

为什么 TCP 需要四次挥手?三次挥手不行吗?

核心:TCP是全双工的协议,需要双方确认自己不再发送数据的时候,才会主动发送FIN报文。分析每次挥手的目的,如果缺少某一次挥手会出现什么问题

为什么需要四次挥手?=》TCP 是全双工协议,双方都具备发送和接收的能力,那么在断开连接的期间,要确保双方能发送完自己的数据。否则可能出现一方数据还没发送完就被迫关闭连接的情况,进而导致数据丢失。

为什么三次挥手不行?=》当客户端发送第一次挥手(发送FIN 报文)后,其实就代表客户端告诉服务端“我不会再发送数据了”服务端收到后,服务器收到客户端的 FIN 报文时,内核会马上回一个 ACK 应答报文,但是服务端应用程序可能还有数据要发送,所以并不能马上发送 FIN 报文,而是将发送 FIN 报文的控制权交给服务端应用程序,如果服务端应用程序有数据要发送的话,就发完数据后再调用关闭连接的函数(所以第二次挥手和第三次挥手通常不会合并一起发送,而是分开发送),第4次挥手则是对第3次挥手的应答。如果只有三次挥手,那么就可能出现一方还有数据没有发送完就被迫关闭连接的情况,这会导致数据的丢失

TIME_WAIT 是如何产生的?

​ 准确来说TIME WAIT状态发生在主动关闭连接的一方,也就是说客户端和服务端都可以作为主动关闭连接的一方

​ 当TCP 连接的主动关闭方关闭连接,与被动关闭方进行了四次挥手的时候,在主动关闭方发送完第四次挥手后,也就是最后一个 ACK 报文后,主动关闭方的 TCP 连接就会进入到 TIME_WAIT 状态,这个状态会持续2MSL的时长,以确保对方已经收到了最后一个ACK报文

为什么 TIME WAIT 状态要等待 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。

参考

MSL表示TCP报文在网络中最大的存活时长

​ 原因1:为了避免本次连接的历史报文,被新的连接接收到,从而导致出错。等待2MSL就可以让两个方向的报文可以在网络中自然消失,这样新的连接就不会接收到历史报文了。

​ 原因2:为了确保第四次挥手 ACK 报文能被接收,从而帮助被动关闭方正常关闭连接。如果主动关闭方的第四次挥手的 ACK 报文丢失了,由于被动关闭方没有收到这个ACK报文,它会超时重传FIN包,主动关闭方TIME _WAIT状态等待期间会重新发送ACK报文,如果没有TIME_WAIT状态,那么就没办法重新发生ACK 报文,也就没办法帮助被动关闭方正常关闭连接了。

TIME WAIT 过多有什么危害?

核心:结合两个方面进行分析,一是资源占用问题(系统资源、端口资源等),二是客户端和服务端的TIME_WAIT造成的影响是不同的

  • 资源占用问题(过多的TIME_WAIT造成的危害)

    • 占用系统资源,比如文件描述符、内存资源、CPU 资源、线程资源等
    • 占用端口资源(端口资源是有限的,一般可以开启的端口为 32768~61000,也可以通过net.ipv4.ip local_port range 参数指定范围)
  • TIME_WAIT过多对客户端和服务端造成的影响不同

    内核通过"四元组"信息(源IP、源端口、目的IP、目的端口)定位连接

    • 客户端过多TIME_WAIT状态:
      • 如果客户端过多TIME_WAIT状态占满了所有端口,则发起连接可能受限(目的IP+目的端口),无法与【目的IP+目的端口】都一样的服务端建立连接
      • 对于不同的服务端而言,端口是可以重复使用的(因为"四元组"信息定位连接,并不会因为客户端端口一样导致连接冲突,而是要看整体的"四元组"信息)
    • 服务端过多TIME_WAIT状态:
      • 并不会导致端口资源受限,因为服务端只监听一个端口
      • 一个四元组唯一确定一个 TCP 连接,理论上服务端可以建立很多连接,但是 TCP 连接过多,会占用系统资源

怎么解决 TIME WAIT 状态过多的问题?

核心:区分客户端、服务端的TIME_WAIT状态过多问题(此处的客户端指的是主动发起关闭方、服务端指的是被动关闭方)

  • 客户端过多TIME_WAIT状态:开启tcp_tw_reuse参数,当发起新连接的时候,内核会复用处于TIME_WAIT的连接(例如TIME_WAIT超过1s的连接)
  • 服务端过多TIME_WAIT状态:服务端不主动断开TCP连接,将断开TCP连接的主动权交给客户端(例如在应用层设计一个逻辑,当服务端要断开连接的时候则发送一个消息通知到客户端,由客户端来断开tcp连接)

服务端产生大量 TIME_WAT 状态的原因是什么?

核心:TIME_WAT 状态是在”主动关闭方“这一侧的,因此要分析服务端为什么会主动关闭连接

  • 场景1:HTTP没有使用长连接

    • 由于客户端和服务端都是短连接,当服务端响应完HTTP后就主动关闭连接,当有大量的短连接过来就可能导致服务端出现大量的TIME_WAT状态
    • 如果是没有使用长连接的问题,则可以让客户端和服务端都开启HTTP Keep-Alive机制
  • 场景2:HTTP长连接的请求数量达到上限

    • 通过参数设定一条HTTP长连接上最大能处理的请求数量,当超出最大限制时,就会主动关闭连接
    • 例如nginx的keepalive_requests参数(默认100),即每个长连接最多只能跑100次请求,因此当QPS很高的时候,nginx会频繁的关闭连接,那么此时服务器就会出现大量的TIME_WAIT状态。可以适当调大这个参数

服务端产生大量 CLOSE_WAIT 状态的原因是什么?

服务端没有调用close函数关闭连接导致

核心:CLOSE_WAIT状态是在”被动关闭方“这一侧的,如果被动关闭方没有调用close函数关闭连接,则无法发送FIN报文,CLOSE_WAIT状态的连接就无法转变为LAST_ACK状态

​ 如果服务端作为被动关闭方没有及时调用close函数关闭连接,则会导致出现大量的CLOSE_WAIT状态的连接(只有正确调用了close函数关闭连接,TCP的连接状态才会从CLOSE_WAIT状态转变为LAST_ACK状态)

​ 如果出现这种情况,那么大概率可能是服务端的代码问题,需要根据代码一步步进行排查和定位,分析为什么服务端没有调用close

如果server发送FIN之后,因为client挂掉了,收不到回应,会发生什么?

核心:只要发送的数据没有收到响应,就会触发”超时重传“,当重传达到最大次数之后还是无响应,就会关闭连接

​ 如果server发送FIN之后client挂掉则无法响应,server会触发”超时重传“,如果重传达到最大次数之后还是没有收到响应,则server就会断开连接

如果客户端宕机重启,收到server的FIN,会发生什么?

​ 客户端宕机重启,那么此前的TCP连接信息就不存在了,如果此时收到server的FIN,则会回RST报文给server,server收到RST报文则会断开连接

3.TCP 与 UDP

TCP 和 UDP 有什么区别?

核心:从 连接、可靠性、传输方式 三个方面进行分析

  • 连接
    • TCP是面向连接的协议,在发送数据的时候需先建立”TCP三次握手“
    • UDP是无连接的协议,直接可以发送数据
  • 可靠性
    • TCP会通过超时重传、流量控制、拥塞控制保证数据的可靠传输
    • UDP无法保证数据的可靠性
  • 传输方式
    • TCP以字节流的形式发送数据,没有边界
    • UDP以包的形式发送,存在边界

​ 综合来看,TCP的优势在于可以确保数据传输的可靠性,但是实时性没有UDP协议好;而UDP的优势在于足够简单(不用建立连接,可以直接发包),在实时性和速度方面是较TCP好的

什么时候用 TCP? 什么时候用 UDP?

核心:TCP、UDP的应用场景选择从”可靠性“、”实时性“进行择选,看关注哪些方面

  • TCP:实时性和传输速度慢,数据传输的可靠性高(例如FTP协议、HTTP协议都是基于TCP协议进行数据传输)
  • UDP:实时性和传输速度快,但不保证数据传输的可靠性(例如直播、视频会议场景)

此时此刻的视频面试用的 UDP 还是 TCP?UDP丢包会有什么现象?

核心:考察TCP、UDP的应用场景

​ 一般是UDP协议,因为视频会议这个场景下,关注的是数据的实时性

  • UDP协议实时性比TCP好,采用UDP协议传输音视频数据的话,如果发生了丢包,只是就丢失某一瞬间的画面和语音,然后还可以继续进行会议沟通,不会太影响视频会议的体验
  • 如果是采用 TCP 协议的,由于 TCP 是可靠传输,如果发生了丢包,可能画面就卡住不动,等丢包重传才会推进画面,这样实时性就比较差了

UDP 怎么改造变为可靠传输?

核心:可以参考TCP协议是如何实现可靠传输,从核心点切入(TCP会通过超时重传、流量控制、拥塞控制保证数据的可靠传输)

​ 按照 TCP 协议怎么实现可靠传输的方式(超时重传、流量控制、拥塞控制),在应用层实现一遍,可以进一步补充说明基于UDP 协议实现的可靠传输相比于 TCP 有什么优势

​ 在应用层进行设计,实现可靠传输:

  • 在应用层增加序列号和确认号

    • 增加序列号字段,用来确保UDP的数据可以按序接收
    • 增加确认号用来实现超时重传机制,当超过一定时间内没收到已发送数据的确认号,就重传该数据包
  • 在应用层开辟缓冲区,用于实现滑动窗口

    • 基于滑动窗口可以批量发送数据,不需要等上一个数据的确认了才能发送,提高了发送速率
    • 基于滑动窗口实现流量控制,用来保证发送方能按接收方的接收能力发送数据,避免发送的数据对方接收不了而发生数据丢
  • 拥塞控制:为了保证整个网络的带宽环境,还需要实现拥塞控制,确保发送方的数据,不会占满整个带宽

​ UDP实现可靠传输相比TCP实现可靠传输的优势:

  • 升级灵活:TCP是在内核实现,而UDP是在应用层实现,如果升级TCP需要升级操作系统,如果升级UDP只需要类似升级应用层协议即可
  • 拥塞控制算法:拥塞控制算法可以根据不同的应用选用不同的算法,UDP是在应用层实现可靠传输因此可以灵活选用,而TCP时基于内核实现,因此其选用时则是所有应用都使用这一套拥塞控制算法
  • 网络连接迁移:UDP在应用层拥连接ID来唯一标识一个连接,而不需要像TCP那样通过”四元组“信息来定位连接(只要四元组信息发生变化,就需要重新建立连接)

TCP 和 UDP 可以共用一个端口吗?

​ socket 是根据五元组信息唯一确认的:协议类型、源 ip 地址、源端口、目标ip地址、目标端口,只要有一个信息不同,就会认为是不同的 socket,不会引起冲突,所以TCP和UDP是可以共用一个端口号的。

4.TCP 可靠性

TCP 是如何保证可靠性的?

核心:从连接建立、序列号和确认号、重传机制、滑动窗口机制、拥塞控制方面进行回答

  • 连接建立:TCP 建立连接的时候,需要三次握手,这个过程可以证明双方都具有发送和接收的能力,并且能避免历史连接的建立
  • 序列号与确认号:TCP 头部由序列字段(保证数据的有序性)和确认号(用于确认收到了数据)
  • 数据重传机制:如果发送方发送的数据,长时间没有收到确认报文,就会触发超时重传,重传丢失的报文
  • 滑动窗口机制:发送方会根据接收方的接收窗口来发送数据报文,可以避免发送方发送的数据报文太大,导致接收方接收不了而丢包的问题
  • 拥塞控制机制:通过慢启动、拥塞避免、拥塞发生,快速重传和快速恢复等算法调整发送速率来避免网络拥塞。当网络出现拥塞时,TCP 会降低发送速率,以减少网络负载,保证数据的可靠传输

TCP流量控制和拥塞控制的区别?

核心:控制的层面不一样,流量控制是端到端、拥塞控制是网络层面的控制

​ 流量控制和拥塞控制都是TCP实现可靠运输的重要因素,其区别在于:流量控制关注的是保护接收方不被淹没,而拥塞控制关注的是保护网络不被过载

  • 流量控制(关注端到端的控制):防止发送方发送数据过快,导致接收方处理不过来(通过流量窗口机制实现,接收方在ACK报文中告知发送方自己的接收窗口大小,以限制发送数据量)
  • 拥塞控制(关注网络层面的控制):防止过多的数据包同时在网络中传输,导致网络拥塞(通过慢启动、拥塞避免、拥塞发生、快速重传、快速恢复这几种算法实现)

滑动窗口怎么设计的?解决什么问题?

核心:滑动窗口的设计涉及两个方面,一个是”发送窗口“、一个是”接收窗口“

发送方和接收方在内核各自都有一个缓冲区,发送缓冲区和接收缓冲区上都各有一个窗口,发送方的窗口表示可发送的最大数据量,接收方的窗口表示可接收的最大数据量。

  • 发送窗口"提速":发送方可以不用等待已发送数据的确认报文,就可以继续发送下一批数据,提高了发送的速率
  • 接收窗口"限流":实现流量控制,把接收方的接收窗口告诉给发送方,让发送方按自己的接收情况来发送数据,避免发送方发送的数据过快,导致接收方处理不过来

TCP 协议拥塞控制是怎么实现的?

​ TCP协议的拥塞控制主要通过五个算法来实现:慢启动、拥塞避免、超时重传、快速重传和快速恢复。这些拥塞控制算法,可以让TCP协议能够根据网络状况动态调整发送速率,避免因为过大的流量导致网络拥塞

  • 慢启动:发送方开始时设置一个较小的拥塞窗口大小,在每收到一个对新的报文段的确认后,每当成功发送跟拥塞窗口大小等量的数据后,拥塞窗口大小就会翻倍,以指数方式增长,直到拥塞控制窗口达到慢启动门限
  • 拥塞避免:当窗口大小达到慢启动门限后,就进入拥塞避免阶段,每当成功发送跟拥塞窗口大小等量的数据后,拥塞窗口大小就会增加一个报文段的大小,以线性方式增长
  • 拥塞发生:随着发送速率慢慢增长,可能网络会出现拥塞,发生了数据包丢失,这时候就需要重传数据,重传机制主要有两种(超时重传和快速重传)
    • a.超时重传:当发生了超时重传,慢启动门限会设置为拥塞窗口的一半,并且将拥塞窗口恢复为初始值接着,就重新开始慢启动,发送速率就会瞬间下降了很多
    • b.快速重传和快速恢复:当发送方连续收到三个重复确认时,就认为发生了丢包,这时候拥塞窗口会减少到原来的一半,然后慢启动门限设置为减少后的拥塞窗口大小,然后进入到快速恢复阶段,这时候会把拥塞控制窗口+3,3的意思是确认有3个数据包被收到了,然后重传丢失的报文,如果收到重传丢失报文的 ACK 后,将拥塞窗口设置为慢启动门限,这样就直接进入拥塞避免,继续增大发送速率

TCP的延迟应答和累计应答是什么?

TCP的延迟应答:指接收方不立即发送ACK确认接收到的数据,而是延迟一段时间后再发送ACK。这样可以等待是否有更多的数据要发送,从而减少ACK报文的数量,提高网络利用率

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

5.TCP 场景

TCP 拆包粘包原因是什么?怎么解决?

核心:说明拆包和粘包问题产生的原因,然后给出解决方案

​ TCP的数据传输是基于字节流方式(面向字节流协议),它并不关心数据包的边界:

  • 拆包:如果发送的数据包超过MSS大小或者接收窗口大小,则会被拆分为多个TCP段发送(站在应用层的角度看起来是一个完整的数据包被拆开了)
  • 粘包:如果发送的数据包太小,TCP有一个Nagle算法会将多个小数据包堆积成一个TCP段发送(看起来就会感觉数据包是粘合在一起发送的)

​ TCP的拆包和粘包问题并不是TCP的问题,而是因为TCP的特性才出现的现象,因此要解决拆包和粘包问题需要在应用层进行处理:

  • 固定消息长度的方式
    • 当接收方累计读取到固定长度时则认为已获得一个完整的信息,当发送方的数据小于固定长度时则空位补齐
    • 缺点在于无法很好设定固定长度值,长度太大会造成字节浪费,长度太小则影响消息传输,因此一般不建议采用
  • 特定分隔符的方式
    • 在每次发送报文的尾部加上特定的分隔符,接收方根据特殊分隔符进行消息拆分
    • 例如HTTP请求报文就是通过空白行的方式分隔请求头和请求体(需注意分隔符的选择,避免和消息体中的字符相同)
  • 消息长度+消息内容的方式
    • 消息头存放消息的总长度,消息体位实际的二进制的字节数据。接收方解析数据先读取长度,然后根据长度读取相应的报文,进而获得完整的数据报文
    • 优点在于比较灵活,不会存在”固定消息长度“、”特定分隔符“这两种方式的缺陷,消息头中还可灵活存储其他扩展字段

TCP 的 keepalive 了解吗?说说它和 HTTP 的 keepalive 的区别?

​ 实现的层面不同:

  • HTTP的Keep-Alive:由应用层(用户态)实现,称为HTTP长连接
    • 可以使得用同一个 TCP 连接来发送和接收多个 HTTP 请求和应答,减少了 HTTP 短连接带来的多次 TCP 连接建立和释放的开销
  • TCP的Keepalive:由TCP层(内核态)实现,称为TCP保活机制
    • 当客户端和服务端双方长达一定时间没有进行数据交互时,内核为了确保该连接是否还有效,就会发送探测报文,来检测对方是否还在线,然后来决定是否要关闭该连接

MTU是啥? MSS是啥?

MTU:一个网络包的最大长度,以太网中一般为 1500 字节。当IP 层有一个超过 MTU 大小的数据要发送,那么 IP 层就要进行分片,把数据分片成若干片,保证每一个分片都小于 MTU。

MSS:除去IP 和 TCP 头部之后,一个网络包所能容纳的TCP 数据的最大长度。当 TCP 层有一个超过MSS 大小的应用数据,那么 TCP 层就要针对应用层数据进行分片,把数据分片成若干片,保证每一个分片都小于 MSS。

IP层会分片,为什么TCP层还需要MSS呢?

​ 如果交给IP来进行分片,如果某一个IP 分片丢失了,整个IP 报文的所有分片都得重传。因为IP 层本身没有超时重传机制,它由传输层的 TCP 来负责超时和重传。当某一个 IP 分片丢失后,接收方的 IP 层就无法组装成一个完整的 TCP 报文(头部+数据),也就无法将数据报文送到 TCP 层,所以接收方不会响应 ACK 给发送方,因为发送方迟迟收不到 ACK 确认报文,所以会触发超时重传,就会重发整个 TCP 报文(头部+数据)。

​ 应用层的数据在 TCP 层经过 MSS 分片之后,每一个分片都具备 TCP 头部信息。经过 MSS 分片后的报文,如果某一个丢失了,只需要重传这一个丢失的 TCP 报文就可以了,而不用重传所有的分片,大大增加了重传的效率。

一个服务端进程最多可以建立多少条 TCP 连接?

核心:TCP是通过四元组信息定位连接的:源地址、源端口、目标地址、目标端口,服务端一般固定监听一个端口等待客户端连接请求

​ 服务端进程通常是会固定监听一个端口,等待客户端的连接请求,假设服务端的IP 地址和端口号都是不变,那么一个服务端进程最大能支持的理论连接数等于客户端的IP数量*客户端的端口数量(客户端的IP数量最大为232 ,客户端的端口数量最大为216,计算得出最大能支持的理论连接数为248),这个只是一个理论值,实际上服务端还会受系统资源的限制,比如文件描述符的最大数量、CPU和内存资源

一个机器最多可以建立多少条 TCP 连接?

核心:TCP四元组说明,分析理想情况支持和限制条件

​ 一条 TCP 连接是由四元组组成的,服务器设备上可以有多个进程监听多个端口,然后如果服务器所有端口都被用来监听的话,理论上最大可以建立的TCP 连接数=客户端IP数x客户端端口数x服务端端口数,即2^32 x 2^16 x 2^16。这个只是理论值,实际中TCP的连接建立是要消耗资源的,受限于服务器硬件资源配置,比如内存资源的限制,参考每一条静止的 TCP 连接内存占用大概 3.3K,如果服务器的物理内存是 4G,那么最大只能建立 100 万左右(4GB/3.3KB)的连接

如果已经建立了连接,但是服务端突然出现断电了会发生什么?

核心:根据不同情况进行分析(客户端是否会发送数据?客户端有没有开启TCP保活机制?)

  • 如果客户端接下来会发送数据:

    • 由于服务端断电了,客户端已发送的数据就没办法得到确认,于是就会发生超时重传,重传次数达到上限之后,客户端就会断开 TCP 连接
  • 如果客户端接下来不会再发送数据,则进一步确认客户端有没有开启 TCP 保活机制

    • 如果没有开启TCP 保活机制,客户端的TCP状态将一直保持不变;
    • 如果开启了TCP 保活机制,双方超过一段时间没有进行数据交互的话,内核就会触发TCP 保活机制定时发送探测报文,由于这段时间服务端断电了,客户端发送的探测报文都不会得到响应,当探测次数达到上限时如果还未收到响应的话,客户端就会断开 TCP 连接

如果已经建立了连接,但是服务端的进程崩溃会发生什么?

​ TCP 的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有TCP 连接资源,于是内核会发送第一次挥手 FIN 报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成 TCP四次挥手的过程。

服务端进程崩溃的话,内核会负责回收服务端进程的资源,会发送 FIN 报文,和客户端进行四次挥手断开连接

TCP 中 SYN 洪水是什么?如何防止?

​ TCP 连接建立是需要三次握手,假设攻击者短时间伪造不同IP地址的 SYN 报文,服务端每接收到一个 SYN报文,就进入 SYN_RCVD 状态,但服务端发送出去的 ACK + SYN 报文,无法得到未知IP 主机的 ACK 应答,久而久之就会占满服务端的 TCP 半连接队列,使得服务端不能为正常用户服务。

解决方式

​ (1)开启 tcp 的 syn cookie 机制,它可以在服务端第二次握手的时候,生成一个伪随机的序列号,用于验证客户端的SYN包。只有在客户端回应服务器的ACK包时,服务器才会分配资源,所以可以在不使用 SYN 半连接队列的情况下成功建立连接,相当于绕过了 SYN 半连接来建立连接。

​ (2)其次可以通过调整内核参数来增大半连接队列的大小,以及减少 syn+ack 重传的次数来避免 SYN 洪水攻击

网络层

1.网络层题型

ping 的工作原理说一下

​ 例如ping 180.101.50.242ping baidu.com

​ ping 是通过ICMP协议来实现的,ping的时候会发送类型为回送请求的ICMP报文,对方接收到之后,就会回复类型为回送应答的ICMP报文

​ 在规定的时间内,源主机如果没有接到ICMP的应答包,则说明目标主机不可达,如果接收到了ICMP回送响应消息,则说明目标主机可达

交换机和路由器有什么区别?

核心:两者的网络层级和功能不一样

  • 交换机工作在 MAC 层(称为二层网络设备),主要处理数据帧的转发和交换,交换机会根据MAC地址来转发数据包,实现局域网内设备之间的通信
  • 路由器工作在 IP 层(称为三层网络设备),主要负责IP数据包的转发和路由选择,路由器会根据IP地址来转发数据包,实现不同网络之间的通信

什么是IP地址?

​ IP地址是用于在计算机网络上唯一标识和定位网络中的设备,IP地址允许计算机在网络上相互通信和交换数据

​ 在TCP/IP协议中,IP地址与MAC地址结合使用,实现了设备之间的通信和数据传输。

什么是 mac 地址?

​ MAC地址是在数据链路层中使用的标识符,只在局域网范围内有效。在互联网通信中,数据包最终是通过IP地址来路由和传递的,而在局域网中则是通过MAC地址来实现设备之间的直接通信。

​ MAC地址与IP地址结合起来,共同协助实现了数据在网络中的正确传输和交换。

IP地址和MAC地址有什么区别?

  • IP地址用于在网络中唯一标识和定位设备,它是在网络层使用的地址,用于实现不同网络之间的通信

  • MAC地址用于在局域网中唯一标识和定位设备,它是在数据链路层使用的地址,用于实现局域网内设备之间的通信。

为什么有了IP地址,还需要MAC?

核心:可以从只有 mac 没有 ip 会有什么问题,只有ip 没有 mac 会有什么问题 进行说明

如果只有MAC没有IP,网卡的实现上极其困难:如果只使用MAC地址的话,路由器就需要记住每个MAC地址所在的子网是哪一个,而世界上有2的48次方个MAC地址,这就意味着即使给每个 MAC 地址只留1字节的储存空间,每个路由器也需要 256 TB 的内存,这显然是不可能实现的

如果只有IP没有MAC:IP地址是要设备上线以后,才能根据他进入了哪个子网来分配的,在设备还没有IP地址的时候(或者分配IP地址的过程中),还需要用MAC地址来区分不同的设备,并根据MAC地址通信

NAT是什么协议?

NAT协议在网络层工作,会将私有IP地址转换为公网IP地址,这样可以实现局域网的设备与互联网其他设备的通信

NAT协议比较常见的转换操作是端口转换,多个私有IP地址可以共享一个公网IP地址,通过端口来区分不同的私有IP地址。所以,NAT协议的优势在于可以节省公共IP地址资源,因为多个内部设备可以共享同一个公共IP地址

192.168.1.100/24 中的斜杠代表 什么意思?

​ 斜杠(/)后面的数字表示子网掩码的位数(掩码的意思:掩盖掉主机号,剩余的就是网络号)

​ 比如192.168.1.100/24中的斜杠后面的数字 24 表示子网掩码的位数,子网掩码用于划分IP地址中的网络部分和主机部分,即表示前 24 位是网络部分,后 8 位是主机部分。将子网掩码和IP 地址进行与运算,就可以得到网络号

网络攻击

1.网络攻击题型

DNS 劫持是什么?

​ DNS劫持就是黑客劫持了DNS服务器,篡改了DNS解析结果,将client请求的域名解析到错误的IP地址上,让真实服务器拿不到请求,更多发生在诱导、钓鱼、广告植入、诈骗等诸多场景。

​ 解决办法:手动更换公共DNS服务器,绕过被劫持的DNS服务器

image-20240827140950388

参考:当访问网站时,会先进行域名解析得到网站服务器的IP,然后再进行后续的访问。DNS劫持则是利用这个过程中的漏洞,攻击者在DNS服务器上篡改DNS解析结果,将域名解析到攻击者控制的恶意服务器上,则此时访问的域名就被重定向到恶意网站上

DNS 污染是什么?

DNS污染是一种让一般用户由于得到虚假目标主机 IP 而不能与其通信的方法,是一种 DNS 缓存投毒攻击(DNS cache poisoning)。其工作方式是:由于通常的 DNS 查询没有任何认证机制,而且 DNS 查询通常基于的 UDP 是 无连接不可靠 的协议,因此 DNS 的查询非常容易被篡改,通过对 UDP 端口 53上的 DNS 查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者返回虚假结果

image-20240827141906005

DNS污染症状:目前一些在被禁止访问的网站基本都是通过DNS污染来实现的,例如 YouTube、Facebook 等网站

​ 解决办法:

  • (1)绕过被污染的非权威 DNS 服务器,直接访问干净的公共 DNS 服务器
  • (2)在本机直接绑定hosts,绕过 DNS 解析过程(但由于 IP 地址会变更,故本机的 hosts 也需要不断更新)

参考:DNS污染就是得到了一个虚假的结果,攻击者监听DNS查询,一旦发现查询的域名与自己是匹配的,就把自己伪装成目标域名服务器,然后返回虚假的结果给用户,这样用户域名解析的结果就是错误的,无法和正确的目标服务器 IP 进行通信

简述 DDOS 攻击原理,如何防范它?

思路:解释什么是DDOS攻击?有什么症状?DDOS攻击类型?如何避免DDOS?

​ DDOS 攻击就是用大量的僵尸计算机对服务器发送大量的请求,让服务器的带宽、CPU和内存耗尽,让服务器超载后,无法再对外提供正常的服务。DDOS 攻击根据不同的分类标准分为多种类型(应用层攻击、传输层攻击、网络层攻击):

  • 应用层攻击:旨在让真实用户无法正常使用应用程序,常见的有ICMP 洪水攻击、ARP 洪水攻击和IP分片攻击
  • 传输层攻击:旨在使目标服务器或者网络设备过载,常见的有 SYN 洪水攻击、ACK 洪水攻击、UDP洪水攻击
  • 网络层攻击:旨在消耗网络带宽资源,常见的有DNS洪水攻击、HTTP 洪水攻击和CC攻击

​ 可以通过下述几个方面防御 DDOS 攻击:

  • 限制单个 IP 地址的请求频率,并且对异常流量的 IP 地址,拉黑名单,配置防火墙规则,阻止恶意流量请求
  • 增加用户验证机制,使用验证码、人脸识别等方式,增加用户验证的难度,减少恶意请求的影响
  • 花钱买可靠的DDOS防护服务提供商,他们具备强大的网络基础设施和专业的防护技术,能够识别和过滤掉恶意流量,确保正常的服务运行

什么是 XSS 攻击? 如何防止?

​ 存储型 XSS 攻击又称为持久性跨站点脚本攻击,通常攻击者将一些恶意的脚本代码存储到漏洞服务器中(例如一些评论或者发帖等),用户浏览相关页面时,浏览器执行了该恶意脚本进而被攻击,脚本攻击步骤:

(1)攻击者将恶意脚本代码上传或存储到漏洞服务器

(2)服务器把恶意脚本保存到服务器

(3)当正常客户访问服务器时,服务器会读取恶意数据并且直接使用

(4)服务器会返回含有恶意脚本的页面

实际案例

(1)譬如发帖中发出包含恶意代码的内容,其他内容访问到该内容后,满足特定条件后条件即触发

(2)后台不过滤信息,并且前端展示时也不过滤信息

​ 注意:这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等

防止 XSS 攻击

输入验证和过滤:过滤一些特殊的字符,比如 javascript 脚本中的 <>进行转移 <>再进行存储,这样就能有效的进行 xss 攻击的预防

使用HTTP-only Cookie:将敏感信息存储在HTTP-only Cookie中,限制]avaScript的访问权限,防止恶意脚本窃取用户的Cookie信息

什么是 CSRF 攻击?如何防止?

​ CSRF(Cross-site request forgery,跨站点请求伪造攻击):攻击者通过跨站请求,以合法的用户身份进行非法操作,如转账交易、发表评论等。其核心是利用了浏览器 Cookie 或服务器的 Session 策略,盗取用户的身份信息后进行恶意操作。

image-20240827150143261

案例分析

​ 用户先登录银行A网站,获得了A网站的Cookie,然后此时用户不消息浏览了一个恶意B网站,B网站让用户向银行A发起转账请求,诱导用户进行转账,由于此时用户已有A网站的Cookie,则操作有可能成功,进而造成非本人意愿的结果

如何防范

同源检测:在服务器端对请求进行同源检测,只接受来自同一域名下的请求(可以通过检查请求头中的Referer字段或者Origin字段来实现)

使用验证码:对于敏感操作,要求用户输入验证码进行验证,以防止自动化脚本发起的恶意请求

使用CSRF令牌:在用户执行敏感操作时,要求用户提交一个CSRF令牌。该令牌是一个随机生成的字符串,存储在用户的会话中,并且在每个请求中都要验证该令牌的有效性。攻击者无法伪造正确的SRF令牌,从而防止CSRF攻击

什么是 SQL 注入攻击?如何防止?

​ SQL 注入攻击是攻击者在 HTTP 请求中注入恶意 SQL 语句,让服务端执行到了恶意的SQL语句时,可能对数据库造成全量数据拉取、删除、更新等敏感的操作。预防SOL注入攻击,可以通过这几个方式:

  • 使用参数化查询或预编译语句:使用参数化查询或预编译语句来构建和执行SOL查询,这样可以将用户输入的数据作为参数传递给查询,而不是将其直接拼接到S0L语句中,参数化查询可以防止恶意代码的注入
  • 输入验证和过滤:对用户输入的数据进行验证和过滤,确保只接受合法的输入,可以使用白名单过滤、正则表达式验证或者编码转义等技术来防止恶意代码的注入
  • 最小权限原则:在数据库中为应用程序使用最小权限的数据库账户,这样即使发生SOL注入攻击,攻击者也只能在该账户的权限范围内进行操作,减少损失

网络编程(TX/Byte)

1.网络编程常见题型

Socket 网络编程对应 TCP 三次握手的环节

image-20240827153838844

核心:scoket网络编程中connect、bind、listen、accept函数的作用

  • (1)服务端首先会通过 bind 函数给 socket 绑定端口和IP地址,然后调用 listen 函数进行监听,然后调用accpet 函数等待客户端建立连接

  • (2)当客户端调用 connect 函数的时候

    • 【A】内核会随机生成初始化序号,放到 TCP 报文头部的序号字段中
    • 【B】把 SYN 标志设置为 1(标识为SYN报文)
    • 【C】把这个 SYN 报文发送给服务端,之后客户端处于 SYN_SENT 状态
  • (3)服务端收到 SYN 报文后,服务端执行下述操作

    • 【A】随机生成初始化序号,放到 TCP 报文头部的序号字段中
    • 【B】对客户端的初始化序号+1作为确认号,放到 TCP 报文头部的确认应答字段中
    • 【C】将 SYN 和 ACK 标志设置为1(标识为SYN-ACK报文)
    • 【D】把该报文发给客户端,之后服务端处于 SYN_RCVD 状态
  • (4)客户端收到服务端SYN-ACK报文后

    • 客户端会回一个 ACK 确认报文,该报文的确认号是服务端的初始化序号+1,并且 ACK 标志会设置为 1,之后客户端处于 ESTABLISHED 状态,这时候 connect 函数就返回了
  • (5)服务端收到 ACK 确认报文后,服务端也进入处于 ESTABLISHED 状态,此时 accpet 函数就返回已建立连接的 socket 了,后续与客户端进行通信,就是对这个 socket 进行读写操作

建立TCP连接,Socket 在 TCP 握手哪个阶段可以拿到连接?

​ 需要完成三次握手后,服务端才能通过accept函数得到已经建立TCP连接的socket

listen 的参数 backlog 意义是什么?

Linux内核中会维护两个队列

半连接队列(SYN 队列):接收到一个 SYN 建立连接请求,处于 SYN RCVD 状态;

全连接队列(Accpet 队列):已完成 TCP 三次握手过程,处于 ESTABLISHED 状态;

int listen(int socketfd,int backlog),其中socketfd:socketfd文件描述符,backlog(历史版本有一定的变化,早期的backlog是SYN队列大小,在Linux内核2.2之后backlog是accept队列大小)

backlog参数的大小:指定TCP全连接队列大小的参数之一,内核选择min(somaxconn,backlog)作为TCP全连接队列的大小

当客户端多次发送连接,服务器没有accept,客户端会出现什么现象?

​ 会导致客户端无法和服务端建立TCP 连接,因为如果服务端没有执行 accpet 的话,那么已经建立连接的scoket会堆积到TCP全连接队列,如果 TCP 全连接队列占满了,服务端收到新的客户端 SYN 报文的时的 socket 会堆积到 TCP 全连接队列,候,内核就会丢弃 SYN 报文。

四次挥手对应socket中通信的部分,其中哪些是用户调用,哪些是内核完成的?

​ 四次挥手中的第1次挥手和第3次挥手中的FIN报文,需要由客户端或者服务端调用close函数触发(属于用户调用),第2次和第4次挥手的ACK则是由内核来完成

如果客户端和服务端同时调用了close()会发生什么?

​ TCP是双全工的协议,所以会出现双方同时关闭连接的情况,即同时发送了FIN报文

​ 双方会同时发送 FIN 报文,由于双方在等待 ACK 报文的过程中,都等来了 FIN 报文,这是一种新情况,所以连接会进入一种叫做 CLOSING 的新状态,它替代了 FIN_WAIT_2 状态。接着,双方内核回复 ACK 确认对方发送通道的关闭后,进入 TIME_WAIT 状态,等待 2MSL 的时间后,连接自动关闭

image-20240827152943607

怎么知道客户端关闭连接?

核心:区分正常场景和异常场景分析

​ 如果客户端正常断开连接的情况下,会发起了第一次挥手 FIN 报文,服务端收到后,内核会插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 报文,如果 read 返回0了,就代表客户端关闭连接了

​ 如果客户端突然宕机了,服务端无感知客户端已经不存在了,如果接下来服务端不会在发送任何数据的话,超过一段时间后,TCP 就会开启保活机制,来探测客户端是否还存活,如果最终判断到客户端不存在了,服务端这边也会自动释放连接

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3