收集各路面试问答,做一个记录
1. 网络基础
1.1 问:三次握手和四次挥手
为什么要进行三次握手:为了确认对方的发送和接收能力。
三次握手
三次握手主要流程:
- 一开始双方处于
CLOSED
状态,然后服务端开始监听某个端口进入LISTEN
状态 - 然后客户端主动发起连接,发送
SYN
,然后自己变为SYN-SENT
,seq = x
- 服务端收到之后,返回
SYN seq = y
和ACK ack = x + 1
(对于客户端发来的 SYN),自己变成SYN-REVD
- 之后客户端再次发送
ACK seq = x + 1
,ack = y + 1
给服务端,自己变成EASTABLISHED
状态,服务端收到ACK
,也进入ESTABLISHED
SYN 需要对端确认,所以 ACK 的序列化要加一,凡是需要对端确认的,一点要消耗 TCP 报文的序列化
为什么不是两次?
无法确认客户端的接收能力。
如果首先客户端发送了 SYN 报文,但是滞留在网络中,TCP 以为丢包了,然后重传,两次握手建立了连接。
等到客户端关闭连接了。但是之后这个包如果到达了服务端,那么服务端接收到了,然后发送相应的数据表,就建立了链接,但是此时客户端已经关闭连接了,所以带来了链接资源的浪费。
为什么不是四次?
四次以上都可以,只不过 三次就够了
四次挥手
- 一开始都处于 ESTABLISH 状态,然后客户端发送 FIN 报文,带上 seq = p,状态变为 FIN-WAIT-1
- 服务端收到之后,发送 ACK 确认,ack = p + 1,然后进入 CLOSE-WAIT 状态
- 客户端收到之后进入 FIN-WAIT-2 状态
- 过了一会等数据处理完,再次发送 FIN、ACK,seq = q,ack = p + 1,进入 LAST-ACK 阶段
- 客户端收到 FIN 之后,客户端收到之后进入 TIME_WAIT(等待 2MSL),然后发送 ACK 给服务端 ack = 1 + 1
- 服务端收到之后进入 CLOSED 状态
客户端这个时候还需要等待两次 MSL 之后,如果没有收到服务端的重发请求,就表明 ACK 成功到达,挥手结束,客户端变为 CLOSED 状态,否则进行 ACK 重发
为什么需要等待 2MSL(Maximum Segement Lifetime):
因为如果不等待的话,如果服务端还有很多数据包要给客户端发,且此时客户端端口被新应用占据,那么就会接收到无用的数据包,造成数据包混乱,所以说最保险的方法就是等服务器发来的数据包都死翘翘了再启动新应用。
- 1个 MSL 保证四次挥手中主动关闭方最后的 ACK 报文能最终到达对端
- 1个 MSL 保证对端没有收到 ACK 那么进行重传的 FIN 报文能够到达
为什么是四次而不是三次?
如果是三次的话,那么服务端的 ACK 和 FIN 合成一个挥手,那么长时间的延迟可能让 TCP 一位 FIN 没有达到服务器端,然后让客户的不断的重发 FIN