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

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

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

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

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

PS:ACK、SYN和FIN这些大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。
在这里插入图片描述

三次握手过程

在这里插入图片描述
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

四次挥手过程

在这里插入图片描述
1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

需搞清以下几个问题
1 三次握手过程中每次握手时数据包中都包含哪些信息?

从三次握手示图中即可获知每次握手有 SYN、ACK、seq、ack 的相关信息。

2 四次挥手过程中每次挥手时数据包中都包含哪些信息?

从四次挥手示图中即可获知每次挥手有 FIN、ACK、seq、ack 的相关信息。

3 三次握手过程中每次握手前后客户端与服务端所处的状态有哪些以及这些状态标识什么含义?

从三次握手示图中即可获知每次握手前后客户端与服务端所处的状态有哪些。并且能口述出来。

三次握手过程中客户端与服务端所处状态含义根据示意图中的标注很容易理解。

4 四次挥手过程中每次挥手前后客户端与服务端所处的状态有哪些以及这些状态标识什么含义?

从四次挥手示图中即可获知每次挥手前后客户端与服务端所处的状态有哪些。并且能口述出来。

以下对各个状态的理解只是个人理解:可能不准确,后序还会进行进一步完善。

FIN-WAIT-1: 终止等待1。等待服务端发送ACK包。

CLOSE-WAIT: 关闭等待。此时整个TCP连接半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。全双工通信变单向通信,即服务器向客户端发送数据。

FIN-WAIT-2: 终止等待2。等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

LAST-ACK: 最后确认。等待客户端发送最后的ACK包,收到ACK包后,服务端关闭连接,即服务端关闭socket。

TIME-WAIT: 时间等待。等待2*MSL时间段后,客户端关闭连接,即客户端关闭Socket。

5 为什么连接的时候是三次握手,而不是两次或四次握手?

为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。

如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

6 为什么连接的时候是三次握手,关闭的时候却是四次握手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能Sever端的数据还没有发送完成,并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

7 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?

如果主动关闭方直接进入 CLOSED:

  • [1] 当被动关闭方重传 FIN 时,主动关闭方已经不在监听状态(或者端口被新进程占用),会回复 RST 包,导致被动关闭方非正常关闭。
  • [2] 防止旧连接的“迷途”报文段干扰新连接。TCP 的端口可以被复用。如果主动关闭方立即关闭端口并重新建立相同 IP 和端口的连接,那么上一个连接在网络中延迟(迷途)的报文段可能会在新连接建立后才到达,被新连接误认为是合法数据,导致数据错乱。

补充:

  • MSL(Maximum Segment Lifetime),可译为“最长报文段寿命”。它是任何报文在网络上存在的最长的最长时间,超过这个时间报文将被丢弃。RFC793中规定MSL为2分钟,但这完全是从工程上来考虑,对于现在的网络,MSL=2分钟可能太长了一些。因此TCP允许不同的实现可根据具体情况使用更小的MSL值。
  • TTL(time to live),可译为“生存时间”。我们都知道IP头部中有个TTL字段,这个生存时间是由源主机设置设置初始值但不是但不是存在的具体时间,而是一个IP数据报可以经过的最大路由数,每经过一个路由器,它的值就减1,当此值为0则数据报被丢弃,同时发送ICMP报文通知源主机。
  • RRT(Round Trip Time),可译为“往返时间”。指报文段的往返时间。在不同的网络环境中RTT是不同的。
  • 抖动:RTT 时间波动的值、方差。
  • 重发超时:重发超时既要考虑RRT还要考虑偏差的原因。根据网络环境的不同往返时间可能会产生大幅度的摇摆,之所以发生这种状况是因为数据包的分段是经过不同线路到达的。一般设置为6秒。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。此外,数据不会被无限、反复地重发。达到一定重发次数后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接,并且同之应用通信异常强行终止。
8 如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段(心跳包),以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

[参考博客]
TCP的三次握手与四次挥手理解及面试题(很全面)
TCP三次握手中SYN,ACK,seq ack的含义

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐