计网操作系统最常问八股问题整理
前言
我之前整理过计网操作系统超详细八股笔记:https://www.nowcoder.com/discuss/581630972664332288?sourceSSR=users ,但是说实话因为这份这份八股资料过于详细,内容过于充实,给背记带来了很大的挑战,所以我准备再出一系列帖子,内容就是我根据自己的面试经历和网上的面经,去筛选八股里面哪些是最常被问到的问题把它们整理出来,这样也能省去大家自己整理和筛选的时间,大家可以在面试前一两个小时快速把这一系列最常问八股的帖子拿出来看看,临时抱佛脚的效果应该很好。后面这系列帖子我会放入专栏https://www.nowcoder.com/creation/manager/columnDetail/0ybvLm,欢迎大家订阅。最后我想说,速成虽好,但是还是建议有时间就去看看我详细的八股笔记帖子。
计网
基础知识
1.OSI 七层模型
2.TCP/IP模型
由以下 4 层组成:
- 应用层
- 传输层
- 网络层
- 网络接口层
TCP和UDP
0.udp
1.tcp的单播和udp的多播和广播
- 单播:两个主机间单对单的通信
- 广播:一个主机对整个局域网上所有主机上的数据通信(网络地址全1)
单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网的主机进行通信
3.多播:实际情况下,经常需要对一组特定的主机进行通信,而不是所有局域网上的主机
2.udp怎么解决数据包顺序错乱和丢包的问题/怎么保证可靠传输?
UDP(用户数据报协议)是一种无连接的传输层协议,它提供了不可靠的数据报服务。这意味着UDP本身并不保证数据包的顺序或防止数据包丢失。然而,可以在应用层上实现一些机制来解决这些问题。以下是一些常用的方法:
解决数据包顺序错乱的问题
- 序列号机制: 给每个发送的数据包分配一个唯一的序列号。接收端可以根据序列号重新排序接收到的数据包,确保它们按照正确的顺序处理。
- 确认应答(ACK)机制: 发送方为每个数据包设置一个定时器,并等待接收方的确认。如果在定时器超时前没有收到确认,则可以假设数据包已丢失,并重新发送该数据包。接收方在接收到数据包后,会根据序列号发送确认信息给发送方,以告知哪些数据包已经正确接收。
- 滑动窗口协议: 滑动窗口协议允许发送方连续发送多个数据包而不需要为每一个数据包等待确认。接收方可以使用序列号来识别乱序到达的数据包,并通过累积确认告诉发送方哪些数据包已经被成功接收。
解决数据包丢失的问题
- 超时重传: 结合上述的序列号和确认机制,如果发送方在一定时间内未收到确认,则认为数据包丢失并进行重传。
- 冗余编码: 在发送数据时加入一定的冗余信息(如前向纠错码FEC),这样即使某些数据包丢失,接收端也可以利用剩余的数据包和冗余信息恢复原始数据。
- 混合ARQ(自动重传请求): 结合前向纠错(FEC)与传统的ARQ技术,允许接收方在检测到丢失或错误时尝试自行纠正错误,同时对于无法纠正的情况请求重传。
这些方法都需要在应用程序层面实现,因为UDP本身并没有提供这样的功能。实际上,许多实时通信系统,比如VoIP和视频流媒体服务,都会在其协议栈中包含类似的机制来应对UDP的不可靠性。
1.TCP和UDP的区别?
TCP:传输控制协议,UDP:用户数据报协议。
区别:
1.TCP面向连接,即使用TCP通信双方传输前要三次握手来简历TCP连接;UDP是无连接的,即发送数据之前不需要建立连接,可以随时发送数据。
2.TCP仅支持单播(即一对一通信);UDP支持单播、多播和广播;
3.TCP提供可靠的服务(即不会出现无码、丢失等传输差错);UDP提供不可靠服务。因此,TCP适用于要求可靠传输且对实时性要求不高的应用,如文件传输和电子邮件;而UDP适合视频会议等实时应用。
4.TCP面向字节流,即把应用报文看成一连串无结构的字节流;UDP是面向报文的,即对应用保温既不合并也不拆分而是保留报文的边界。
5.TCP有拥塞控制;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如实时视频会议等)。
6.TCP首部开销20字节;UDP的首部开销小,只有8个字节。
3.TCP 协议是如何保证可靠传输的?
- 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;
- 对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;
- 丢弃重复数据:对于重复数据,能够丢弃重复数据;
- 应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
- 超时重传:TCP在发送一个数据之后,就开启一个定时器,若是在这个时间内没有收到发送数据的ACK确认报文,则对该报文进行重传,在达到一定次数还没有成功时放弃并发送一个复位信号。
- 流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP 使用的流量控制协议是可变大小的滑动窗口协议。
- 拥塞控制 : 当网络拥塞时,减少数据的发送。TCP 在发送数据的时候,需要考虑两个因素:一是接收方的接收能力,二是网络的拥塞程度。接收方的接收能力由滑动窗口表示,表示接收方还有多少缓冲区可以用来接收数据。网络的拥塞程度由拥塞窗口表示,它是发送方根据网络状况自己维护的一个值,表示发送方认为可以在网络中传输的数据量。发送方发送数据的大小是滑动窗口和拥塞窗口的最小值,这样可以保证发送方既不会超过接收方的接收能力,也不会造成网络的过度拥塞。
4.TCP怎么实现流量控制(滑动窗口)
TCP 利用滑动窗口实现流量控制。流量控制是为了控制发送方发送速率,保证接收方来得及接收。接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。
以下是TCP滑动窗口流量控制的基本工作原理:
- 窗口大小:在TCP连接建立时,双方会协商一个初始窗口大小。这个窗口大小是以字节为单位的,并且在数据传输过程中可以动态调整。接收方会在每个ACK(确认)报文中包含当前可用窗口大小的信息。
- 累积确认:当接收方收到数据段后,它不会立即对每一个数据段都发送一个确认,而是等待一段时间看是否能接收到后续的数据段,然后一次性确认所有已经正确到达的数据。这种方式提高了效率,减少了网络上的确认报文数量。
- 流量控制:发送方根据接收到的接收方的窗口大小来决定接下来可以发送多少数据。如果接收方处理不过来,它可以减小窗口大小,甚至设置为0来暂停发送方的数据发送。当接收方处理完一些数据后,它可以再次增加窗口大小,允许发送方继续发送数据。
- 选择性确认(SACK):除了基本的累积确认外,TCP还支持选择性确认。这意味着接收方可以告诉发送方哪些特定的数据块已经成功接收,这样发送方就只需要重传那些确实丢失的数据段,而不是从最后一个确认的序列号开始重传所有数据。
- 快速重传与恢复:当发送方检测到数据包丢失时,它不需要等到超时重传计时器到期就可以重传丢失的数据包。这是通过接收到三个重复的ACK来触发的,表明接收方正在等待某个特定的数据包。发送方会立即重传丢失的数据包,并进入快速恢复算法以调整其拥塞窗口大小。
其他流量控制方法(令牌桶和漏桶)
令牌桶和漏桶是两种流量控制算法,它们各自有不同的特性和适用场景。具体来说:
- 令牌桶:令牌桶通过以固定的速率向桶中添加令牌来控制流量,每个请求都需要消耗一个令牌。如果桶中有可用的令牌,则请求被允许通过;如果桶中没有令牌,则请求会被限制或拒绝。令牌桶能够应对一定程度的突发流量,因为它可以累积令牌,从而在短时间内处理更多的请求。
- 漏桶:漏桶则是以固定容量的桶来控制流量,请求像水流一样以一定的速率流入桶中,超过桶的容量部分会被丢弃。漏桶算法能够平滑地限制请求的速率,但不适合应对突发流量,因为它的容量是固定的,无法临时处理超过平均速率的请求。
在实际应用中,选择使用令牌桶还是漏桶取决于具体的业务需求和流量特性:
- 对于需要限制平均速率的场景:可以选择漏桶,因为它能够确保请求的处理速度不会超过预设的速率。
- 对于需要处理突发流量的场景:令牌桶更为合适,因为它允许在短时间内处理更多的请求,只要这些请求在之前的时间窗口内有足够的令牌积累。
总结来说,令牌桶更适合处理突发流量,而漏桶更适合平滑限制流量。在实际应用中,应根据系统的承受能力和业务需求来选择合适的流量控制算法。
5.TCP的重传机制是什么?
TCP在发送一个数据之后,就开启一个定时器,若是在这个时间内没有收到发送数据的ACK确认报文,则对该报文进行重传,在达到一定次数还没有成功时放弃并发送一个复位信号。
6.TCP 的拥塞控制是怎么实现的?
拥塞控制是为了防止过多的数据注入到网络中让网络过载
为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。
TCP 的拥塞控制采用了四种算法,即 慢开始、 拥塞避免、快重传 和 快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。
- 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。
- 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送方的 cwnd 加 1.
- 快重传与快恢复: 在 TCP/IP 中,快速重传和恢复(fast retransmit and recovery,FRR)是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送。有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机接收到三个重复确认,它会假定确认件指出的数据段丢失了,并立即重传这些丢失的数据段。有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。
7.说说TCP的三次握手
(序号字段seq:本TCP报文段数据载荷的第一个字节的序号;
确认号字段ack:指出希望受到对方下一个TCP报文段的数据载荷的第一个字节的序号,同时也是对之前收到的数据的确认;
确认标志位ACK:值为1表示确认号字段有效;
同步标志位SYN:SYN=1且ACK=0表示是个TCP连接请求报文段;SYN=1且ACK=1表示同意连接请求报文段)
假设发送端为客户端,接收端为服务端。开始时客户端和服务端的状态都是CLOSED
。
- 第一次握手:客户端向服务端发起建立连接请求,客户端会随机生成一个起始序列号x,客户端向服务端发送连接请求报文,其中包含标志位
SYN=1
,序列号seq=x
。第一次握手前客户端的状态为CLOSE
,第一次握手后客户端的状态为SYN-SENT
。此时服务端的状态为LISTEN
。 - 第二次握手:服务端在收到客户端发来的连接请求报文后,会随机生成一个服务端的起始序列号y,然后给客户端回复确认报文段,其中包括标志位
SYN=1
,确认标志位ACK=1
(表示这是个TCP连接请求确认报文段),序列号seq=y
,确认号ack=x+1
。第二次握手前服务端的状态为LISTEN
,第二次握手后服务端的状态为SYN-RCVD
,此时客户端的状态为SYN-SENT
。 - 第三次握手:客户端收到服务端发来的报文后,会再向服务端发送确认报文段,其中包含确认标志位
ACK=1
,序列号seq=x+1
,确认号ack=y+1
。第三次握手前客户端的状态为SYN-SENT
,第三次握手后客户端和服务端的状态都为ESTABLISHED
。此时连接建立完成。
为什么不是两次握手?
之所以需要第三次握手,主要为了防止已失效的连接请求报文段突然又传输到了服务端,导致产生问题。
- 比如客户端A发出连接请求,可能因为网络阻塞原因,A没有收到确认报文,于是A再重传一次连接请求。
- 然后连接成功,等待数据传输完毕后,就释放了连接。
- A发出的第一个连接请求等到连接释放以后的某个时间才到达服务端B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段。
- 如果不采用三次握手,只要B发出确认,就建立新的连接了,此时A不会响应B的确认且A不发送数据,这时候B处于SYN-RECV状态一直等待A发送数据,浪费资源。
8.TCP的4次挥手
客户端先向其TCP发出连接释放报文段(FIN=1,seq=u
),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1
(终止等待1)状态,等待服务端的确认。
服务端收到连接释放报文段后即发出确认报文段(ACK=1,ack=u+1,seq=v
),服务端进入CLOSE-WAIT
(关闭等待)状态,此时的TCP处于半关闭状态,A到B的连接释放。
A收到B的确认后,进入FIN-WAIT-2
(终止等待2)状态,等待B发出的连接释放报文段。
B发送完数据,就会发出连接释放报文段(FIN=1,ACK=1,seq=w,ack=u+1
),B进入LAST-ACK
(最后确认)状态,等待A的确认。
A收到B的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1
),A进入TIME-WAIT
(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL
(最大报文段生存时间)后,A才进入CLOSED
状态。B收到A发出的确认报文段后关闭连接,若没收到A发出的确认报文段,B就会重传连接释放报文段。
第四次挥手为什么客户端要等待2MSL才进入Closed状态?
保证A发送的最后一个ACK报文段能够到达B。这个ACK
报文段有可能丢失,B收不到这个确认报文,就会超时重传连接释放报文段,然后A可以在2MSL
时间内收到这个重传的连接释放报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED
状态,若A在TIME-WAIT
状态不等待一段时间,而是发送完ACK报文段后直接进入Closed状态,则A无法收到B重传的连接释放报文段,然后B就会反复重传连接释放报文段而不会进入Closed状态。
为什么是四次挥手?
在关闭连接时,当Server端收到Client端发出的连接释放报文时,很可能并不会立即关闭SOCKET,即服务端的报文还没有发完,所以Server端先回复一个ACK
确认报文,告诉Client端我收到你的连接释放报文了。只有等到Server端所有的报文都发送完了,这时Server端才能发送连接释放报文,之后两边才会真正的断开连接。故需要四次挥手。
9.TIME-WAIT
为什么出现TIME-WAIT?
主动关闭连接的一方在发送最后一个ACK后进入的一个临时状态,持续2MSL(1MSL是报文的存活时间)的时间长度。
当两个系统通过 TCP 协议进行通信,并且一方决定关闭连接时,会经过一个四次挥手的过程来完成连接的终止。在最后一次确认(ACK)发送之后,主动关闭连接的一方并不会立即释放端口并允许新的连接使用该端口,而是将该连接标记为 TIME_WAIT 状态,并等待一段时间(通常是两倍的最大段生存时间,即 2MSL),以确保最后一个 ACK 已经被被动关闭连接的一方正确接收。这段时间过后,连接才会被完全关闭,并且端口号可以被重新分配给其他服务。
1.TIME_WAIT 状态会导致什么问题
从网络资源的角度看,该状态下的TCP连接占用了本地端口,无法立即释放。由于端口资源有限,大量处于TIME_WAIT状态的连接可能会导致端口资源枯竭,从而影响新的连接建立。尤其是在高并发、短连接的场景下,这个问题尤为显著。例如,服务器可能会因为大量的TIME_WAIT状态而导致新的客户端无法连接。
2.有很多 TIME-WAIT 状态如何解决
当系统中有大量连接进入 TIME_WAIT 状态时,可以通过多种方法来减轻这种状态带来的负面影响。以下是一些常见的解决方案:
- 优化应用逻辑: 减少短连接:尽可能将短连接转换成长连接。例如,Web 应用可以使用 HTTP/1.1 的 keep-alive 特性,这样客户端和服务器之间可以保持一个长期的连接,多次请求复用同一个连接,减少了连接建立和关闭的次数。批量处理请求:在客户端,可以尝试将多个请求打包成一个较大的请求,从而减少连接建立和关闭的次数。
- 使用 SO_REUSEADDR 或 SO_REUSEPORT: 服务器可以设置 SO_REUSEADDR 套接字选项来通知内核,如果端口被占用,但 TCP 连接位于 TIME_WAIT 状态时可以重用端口。
10.TCP的粘包和拆包问题及其解决方案
TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。
为什么会产生粘包和拆包呢?
- 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
- 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
- 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。
解决方案:
- 发送端将每个数据包封装为固定长度
- 在数据尾部增加特殊字符进行分割
- 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小
HTTP
1.HTTP状态码
101 切换请求协议,从 HTTP 切换到 WebSocket
200 请求成功,有响应体
什么是重定向?
重定向(Redirect)是指通过各种方式将网络请求重新定义,使其转向其他位置的过程。这种机制在互联网中广泛应用,例如:
- 网页重定向:当用户访问的URL已经不再使用或内容已迁移至新的URL时,服务器会返回一个重定向状态码(如301永久重定向或302临时重定向),并告知浏览器新的URL,浏览器会自动跳转到新地址。
- 域名重定向:当一个域名被设置为另一个域名的别名时,所有对该域名的请求都会被自动转发到主域名。
- 路由重定向:在网络路由中,数据包的路径选择变化也可以视为一种重定向,即数据包被重新导向至新的路径以到达目的地。
2.POST和GET有哪些区别?各自应用场景?
1.使用场景:GET 用于获取资源,而 POST 用于传输实体主体。
2.参数:GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在实体主体中。
3.安全性:安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。
4.幂等性:幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。所有的安全方法也都是幂等的。即GET幂等,POST不幂等。
3.HTTP各版本的比较
(这部分看上去没什么问的价值,但根据我的面试经历问的很多很多,就是想考你的基础知识的广度)
1.HTTP/1.0 和 HTTP/1.1 有什么区别?
- 连接方式 : HTTP/1.0 为短连接,HTTP/1.1 支持长连接。
- 状态响应码 : HTTP/1.1 中新加入了大量的状态码,光是错误响应状态码就新增了 24 种。比如说,
100 (Continue)
——在请求大资源前的预热请求,206 (Partial Content)
——范围请求的标识码,409 (Conflict)
——请求与当前资源的规定冲突,410 (Gone)
——资源已被永久转移,而且没有任何已知的转发地址。
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏价格永远为19.9元! 不想当架构师的后端开发工程师不是好码农! 此专栏一方面用于存放我的架构设计学习笔记, 另外我会在本专栏加入一系列最常问八股问题帖子,内容就是我根据自己的面试经历和网上的面经,去筛选八股里面哪些是最常被问到的问题把它们整理出来,大家可以在面试前一两个小时快速把这一系列最常问八股的帖子拿出来看看,临时抱佛脚的效果应该很好