TCP的连接与断开

三次握手

主动发起连接建立的应用进程叫做客户端(client)。被动等待连接建立的应用进程叫做服务器(server)。

  • 第一次握手:Client将同步比特SYN置为1(表示这是一个连接请求或连接接受报文),并发送初始报文段序号seq = x(sequence,含义:表明发送数据时的第一个数据字节的序号,每次发送都会自增,自增数值就是发送的字节数,建立连接时连接报文段长度为1)。发送完报文段1之后,客户端进入 SYN-SENT 状态,等待服务器的确认。
  • 第二次握手:Server收到报文段后,如同意,则发回确认。令SYN=1,ACK=1(表示确认号字段ack有效),ack=x+1(含义:表示x之前的我都收到了,希望对方下一次发送x+1),并选择服务器端初始报文段序号 seq=y(含义:表明服务器传送数据时的第一个数据字节的序号,因为TCP是双向传输)。发送完报文段2后,服务器进入 SYN-RECEIVED 状态。
  • 第三次握手:Client收到确认后,则令确认比特ACK=1,发送报文段序号seq=x+1,希望下一次接收的报文段序号ack=y+1,并将该数据报发送给Server。服务器收到后,则成功建立连接。双方都进入 ESTABLISHED 状态,表示连接已建立。

TCP的连接与断开_第1张图片

四次挥手

(主动方为A,被动方为B)

  1. 客户端发送关闭连接的报文段,FIN 标志位1,请求关闭连接,并停止发送数据。序号字段 seq = x (等于之前发送的所有数据的最后一个字节的序号加一),然后客户端会进入 FIN-WAIT-1 状态,等待来自服务器的确认报文;
  2. 服务器收到 FIN 报文后,发回确认报文,ACK = 1, ack = x + 1,并带上自己的序号 seq = y,然后服务器就进入 CLOSE-WAIT 状态。服务器还会通知上层的应用程序对方已经释放连接,此时 TCP 处于半关闭状态,也就是说客户端已经没有数据要发送了,但是服务器还可以发送数据,客户端也还能够接收。客户端收到服务器的 ACK 报文段后随即进入 FIN-WAIT-2 状态,此时还能收到来自服务器的数据,直到收到 FIN 报文段。
  3. 服务器发送完所有数据后,会向客户端发送 FIN 报文段,各字段值如图所示,随后服务器进入 LAST-ACK 状态,等待来自客户端的确认报文段。
  4. 户端收到来自服务器的 FIN 报文段后,向服务器发送 ACK 报文,随后进入 TIME-WAIT 状态,等待 2MSL(2 * Maximum Segment Lifetime,两倍的报文段最大存活时间) ,这是任何报文段在被丢弃前能在网络中存在的最长时间,常用值有30秒、1分钟和2分钟。如无特殊情况,客户端会进入 CLOSED 状态。服务器在接收到客户端的 ACK 报文后会随即进入 CLOSED 状态,由于没有等待时间,一般而言,服务器比客户端更早进入 CLOSED 状态。

TCP的连接与断开_第2张图片

为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

  由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。A发送了FIN=1仅仅表示A不再发送新的数据报了,但是B未必将全部数据都发送给了A,所以B要将所有数据发送过去,并且收到了确认,才能断开连接。

为什么A发送完ACK=1还要保持2*MSL时间?

  1. MSL即报文最大生存时间。保证若B收不到ACK=1重发FIN=1时,A还未关闭。不过这个不是主要原因,毕竟数据已经交互完成了。
  2. 如果不等待2MSL的话, 那么如果正好一个新连接又建立在相同的端口上, 那么上次的FIN包可能被新的连接收到, 导致新的连接出现问题。MSL一般设置30秒,1分钟或者2分钟。

TCP 建立连接为什么要三次握手而不是两次?

  1. 防止已过期的连接请求报文突然又传送到服务器,因而产生错误 在双方两次握手即可建立连接的情况下,假设客户端发送 A 报文段请求建立连接,由于网络原因造成 A 暂时无法到达服务器,服务器接收不到请求报文段就不会返回确认报文段,客户端在长时间得不到应答的情况下重新发送请求报文段 B,这次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后也进入 ESTABLISHED 状态,双方建立连接并传输数据,之后正常断开连接。此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,但是已经进入 CLOSED 状态的客户端无法再接受确认报文段,更无法进入 ESTABLISHED 状态,这将导致服务器长时间单方面等待,造成资源浪费。
  2. 三次握手才能让双方均确认自己和对方的发送和接收能力都正常 第一次握手:客户端只是发送处请求报文段,什么都无法确认,而服务器可以确认自己的接收能力和对方的发送能力正常; 第二次握手:客户端可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常; 第三次握手:服务器可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常; 可见三次握手才能让双方都确认自己和对方的发送和接收能力全部正常,这样就可以愉快地进行通信了。
  3. 告知对方自己的初始序号值,并确认收到对方的初始序号值 TCP 实现了可靠的数据传输,原因之一就是 TCP 报文段中维护了序号字段和确认序号字段,也就是图中的 seq 和 ack,通过这两个字段双方都可以知道在自己发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,如果是两次握手,只有发起方的初始序号可以得到确认,而另一方的初始序号则得不到确认。

你可能感兴趣的:(面试,tcp/ip,网络,linux)