Java后台开发面试实战(二):TCP三次握手四次挥手

感谢牛客网网友提供的面试经验!

1. 解释一下TCP三次握手四次挥手

图片来源于微信公众号:码农求职小助手
Java后台开发面试实战(二):TCP三次握手四次挥手_第1张图片
答: 嗯(稍作思考)…

  • 三次握手简单来说,在数据传输开始前:
    第一次握手:客户端向服务端发送一段用来连接请求的报文,其中SYN=1,ACK=0
    第二次握手:服务器端接收之后,如果同意连接。则返回一段确认的报文,SYN=1,ACK=1
    第三次握手: 客户端收到服务端的确认后,还要再次向服务段给出确认,ACK=1
    三次握手完毕后,客户端与服务器才正式开始传送数据。

三次握手简单来说,在数据传输开始前:

第一次握手:SYN=1(seq=x)SYN=1表示请求连接,seq=x为随机选取序号,发送端由CLOSE进入FIN_SENT状态。
第二次握手:ACK=1(ack=x+1),ACK=1表示确认连接,返回序列号加1是为了让客户端确认我接受到的信息是你发送的。SYN=1(seq=y),代表服务端也请求连接,并返回一个自己指定的序列号。服务端由LISTEN进入SYN_RECD状态。
第三次握手:ACK=1(seq=x+1,ack=y+1)ACK=1表示确认连接;ack=y+1是为了验证传输的准确性,seq=x+1(前面发送的FIN报文段需要消耗一个序号);客户端由SYN_SENT进入ESTABLISHED阶段。服务端收到ACK后进入ESTABLISH阶段。

Java后台开发面试实战(二):TCP三次握手四次挥手_第2张图片

  • 四次握手简单来说,在数据传输结束后:
    第一次挥手:客户端发送一个用来关闭客户端到服务端的数据传送的报文。FIN=1
    第二次挥手:服务端收到FIN包后,发送一个确认包给对方,ACK=1
    第三次挥手:服务端发送一个用来关闭服务端到客户端的数据传送的报文,FIN=1,ACK=1
    第四次挥手:客户端收到FIN后,发送一个确认包,ACK=1。之后等待2MSL(MSL最长报文段寿命)后,保证报文段能够达到B,再进入关闭状态。
    至此,完成四次挥手,客户端与服务器才正式结束数据传输。

四次握手详细来说,在数据传输结束后:

第一次挥手:FIN=1(seq=u)FIN=1表示要求释放连接;seq=u,u等于前面已经传送过的数据的最后一个字节的序号加1。客户端由由ESTABLISHED进入FIN_WAIT_1阶段。
第二次挥手:ACK=1(ack=u+1,seq=v)ACK=1表明确认字段才有效;确认号为ack=u+1,seq=v,等于服务端前面已经传送过的数据的最后一个字节的序号加1。服务端由由ESTABLISHED进入CLOSE_WAIT阶段。
第三次挥手:ACK=1,FIN=1(ack=u+1,seq=w)seq=w(半关闭状态下可能又有数据传入)。服务端进入LAST_ACKj阶段,客户端进入FIN_WAIT_2状态,
第四次挥手:ACK=1(ack=w+1,seq=u+1)seq=w+1(确认序号),seq=u+1(前面发送的FIN报文段需要消耗一个序号)。客户端等待2MSL(MSL最长报文段寿命)后,保证报文段能够达到B,进入CLOSE状态。最后服务端收到报文后进入CLOSE之后。

二. 解释一下SYN、ACK 、FIN 、seq和ack

Java后台开发面试实战(二):TCP三次握手四次挥手_第3张图片

  • 同步SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。SYN这个标志位只有在TCP建产连接时才会被置1,握手完成后SYN标志位被置0。

  • 确认ACK:占1位,仅当ACK=1时,确认号字段才有效。ACK=0时,确认号无效。

  • 终止FIN:用来释放一个连接。FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接。

  • 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。

  • 确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。

PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。原文链接:link.

三. 为什么是三次握手,可以是两次吗?

不可以(非常坚定的语气)。假如以两次握手建立连接,服务端在某一时刻突然收到了一个来自被客户端卡了很久已经丢弃的SYN包,服务端的操作是返回SYN+ACK并且进入工作状态。客户端收到反馈后,无法告诉服务端这是错误的SYN的包,会造成资源的浪费

四. 为什么断开连接需要四次挥手?

答:因为在客户端发送给服务端FIN包后,服务端返回的FIN和ACK包是分开发送的。为什么要分开呢?因为客户端发送给服务端FIN包后,只表示客户端已经没有数据要发送了,但是另一个方向上可能还会有数据传输进来。所以第二次和第三次挥手分开发送,服务端先给出ACK确认信号,表示已经收到FIN请求,然后当自己也可以结束的时候,再次发送FIN信号。是为了为未传输完毕的数据预留时间,所以需要挥手交互需要四次。

五. 为什么 TIME-WAIT 状态必须等待 2MSL 的时间呢?

  1. 为了保证 A 发送的最后一个 ACK 报文段能够到达 B。 A 发送的最后一个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。B 会超时重传这个 FIN+ACK 报文段,而 A 就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着 A 重传一次确认,重新启动 2MSL 计时器。最后,A 和 B 都正常进入到 CLOSED 状态。如果 A 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后立即释放连接,那么就无法收到 B 重传的 FIN + ACK 报文段,因而也不会再发送一次确认报文段,这样,B 就无法按照正常步骤进入 CLOSED 状态。
  2. 防止已失效的连接请求报文段出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。

你可能感兴趣的:(面试)