资讯专栏INFORMATION COLUMN

图解TCP三次握手与四次分手

Nino / 1004人阅读

摘要:三次握手根据下面这幅图我们来看一下三次握手。每个箭头代表一次握手。第三次握手接收到发回的包后,进入状态。到此三次握手完成,与可以正常进行通信了。第三次本地客户端请求会发送一个包,序列号是,号是来回复服务器。

引言

TCP三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化web程序性能的基础。但是大部分教材都对这部分解释的比较抽象,本文我们就利用wireshark来抓包以真正体会整个流程的细节。

三次握手

根据下面这幅图我们来看一下TCP三次握手。p.s: 每个箭头代表一次握手。

第一次握手

client发送一个SYN(J)包给server,然后等待server的ACK回复,进入SYN-SENT状态。p.s: SYN为synchronize的缩写,ACK为acknowledgment的缩写。

第二次握手

server接收到SYN(seq=J)包后就返回一个ACK(J+1)包以及一个自己的SYN(K)包,然后等待client的ACK回复,server进入SYN-RECIVED状态。

第三次握手

client接收到server发回的ACK(J+1)包后,进入ESTABLISHED状态。然后根据server发来的SYN(K)包,返回给等待中的server一个ACK(K+1)包。等待中的server收到ACK回复,也把自己的状态设置为ESTABLISHED。到此TCP三次握手完成,client与server可以正常进行通信了。

为什么要进行三次握手

我们来看一下为什么需要进行三次握手,两次握手难道不行么?这里我们用一个生活中的具体例子来解释就很好理解了。我们可以将三次握手中的客户端和服务器之间的握手过程比喻成A和B通信的过程:

在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。

在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。

在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。

wireshark

上面分析还不够形象,很容易忘记,下面我们利用wireshark来证明一下上面的分析过程。从下面的的输出就可以很容易看出来,必须要经过前面的三次tcp请求才会有起一次http请求。

第一次请求客户端发送一个SYN包,序列号是0。

第二次请求服务器会发送一个SYN和一个ACK包,序列号是0,ack号是1。

第三次本地客户端请求会发送一个ACK包,序列号是1,ack号是1来回复服务器。

四次挥手

以下面这张图为例,我们来分析一下TCP四次挥手的过程。

第一次挥手

client发送一个FIN(M)包,此时client进入FIN-WAIT-1状态,这表明client已经没有数据要发送了。

第二次挥手

server收到了client发来的FIN(M)包后,向client发回一个ACK(M+1)包,此时server进入CLOSE-WAIT状态,client进入FIN-WAIT-2状态。

第三次挥手

server向client发送FIN(N)包,请求关闭连接,同时server进入LAST-ACK状态。

第四次挥手

client收到server发送的FIN(N)包,进入TIME-WAIT状态。向server发送ACK(N+1)包,server收到client的ACK(N+1)包以后,进入CLOSE状态;client等待一段时间还没有得到回复后判断server已正式关闭,进入CLOSE状态。

TCP滑窗

一般在提到TCP三次握手的时候,同样会涉及到TCP滑窗,下面我们补充一下什么是TCP滑窗。如果采用PAR的形式来传递的话,每一次发送方发送完包后必须得到接收方的确认回复,改进一下这个流程,发送端一次可以发送多个包,不必每次等到接收方的ack回复,同时接收端也要告诉发送端自己能接收多少。当然还需要保证顺序性,对于乱序的状况,我们可以允许等待一定时间的乱序,比如先缓存提前到达的数据,然后等待需要的数据,如果一定时间没有达到就drop掉。

TCP滑动窗口可以解决我们上面提到的概念,滑动窗口中的数据主要分为下面几类:

Sent and Acknowledged: 这些数据表示已经发送成功并已被确认的数据。

Sent But Not Yet Acknowledged: 这部分数据称为发送但还没有被确认,数据被发送出去,没有收到接收端的ACK,认为并没有完全发送,这个属于窗口内的数据。

Not Sent, Recipient Ready to Receive: 这部分是尽快发送的数据,这部分数据已经被加载到缓存中,也就是窗口中了,等待发送,接受端已经告诉发送端自己能够完全接受这些包,所以发送方需要尽快发送这些包。

Not Sent, Recipient Not Ready to Reccive: 这些数据属于未发送,因为这些数据已经超出了接收端所能接受的范围。

对于接收端也是有一个接收窗口,类似发送端,接收端的数据有三个分类(注意接收端并不要等待ACK):

Received and ACK Not Send to Process: 这部分数据属于接收了数据但是还没有被上层的应用程序接收,也是被缓存在窗口中。

Received Not ACK: 已经接收,但是还没有ACK。

Not Received: 有空位但是还没有接收数据。

TCP重传机制

下面这部分内容参考自coolshell,我认为写的比较好,所以转过来分享一下,感兴趣的朋友可以阅读一下 :)

TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。

注意,接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?我们要知道,因为正如前面所说的,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。

超时重传机制

一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。

但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。

对此有两种选择:

一种是仅重传timeout的包。也就是第3份数据。

另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。

这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长。

快速重传机制

于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。

比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。

Fast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是,是重传之前的一个还是重传所有的问题。对于上面的示例来说,是重传#2呢还是重传#2,#3,#4,#5呢?因为发送端并不清楚这连续的3个ack(2)是谁传回来的?也许发送端发了20份数据,是#6,#10,#20传来的呢。这样,发送端很有可能要重传从2到20的这堆数据(这就是某些TCP的实际的实现)。可见,这是一把双刃剑。

References

TCP-CONNECTION
TCP-TERMINATION

Contact

GitHub: https://github.com/ziwenxie
Blog: https://www.ziwenxie.site

本文同步发于我的个人博客,转载请于开头明显处声明博客出处 :)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/10099.html

相关文章

  • 简析TCP三次握手四次分手

    摘要:在协议中,协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换窗口大小信息。采用三次握手的办法可以防止上述现象发生。 TCP是什么? 具体的关于TCP是什么,我不打算详细的说了;当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续。它只是一个超级麻烦的协议,而它又是互联网的基础,也是每个程序员必备...

    LucasTwilight 评论0 收藏0
  • Android网络编程8之源码解析OkHttp中篇[复用连接池]

    摘要:构造函数默认空闲的最大连接数为个,的时间为秒通过构造函数可以看出默认的空闲的最大连接数为个,的时间为秒。实例化实例化是在实例化时进行的在的构造函数中调用了省略省略缓存操作提供对进行操作的方法分别为和几个操作。 1.引子 在了解OkHttp的复用连接池之前,我们首先要了解几个概念。 TCP三次握手 通常我们进行HTTP连接网络的时候我们会进行TCP的三次握手,然后传输数据,然后再释放连接...

    fasss 评论0 收藏0
  • 快速理解TCP/IP三次握手四次挥手

    摘要:三次握手建立连接为什么是三次握手,而不是两次或四次,名为传输控制协议,是一种可靠的传输层协议,协议号为。四次挥手三次握手耳熟能详,四次挥手估计就所谓四次挥手即终止连接,就是指断开一个连接时,需要客户端和服务端总共发送个包以确认连接的断开。 TCP/IP三次握手 TCP建立连接为什么是三次握手,而不是两次或四次?TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6。顺便说一句...

    gself 评论0 收藏0
  • 快速理解TCP/IP三次握手四次挥手

    摘要:三次握手建立连接为什么是三次握手,而不是两次或四次,名为传输控制协议,是一种可靠的传输层协议,协议号为。四次挥手三次握手耳熟能详,四次挥手估计就所谓四次挥手即终止连接,就是指断开一个连接时,需要客户端和服务端总共发送个包以确认连接的断开。 TCP/IP三次握手 TCP建立连接为什么是三次握手,而不是两次或四次?TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6。顺便说一句...

    BetaRabbit 评论0 收藏0
  • 关于三次握手四次挥手面试官想考我们什么?--- 不看后悔系列

    摘要:第三次握手客户端收到报文之后,会回应一个报文。因此,需要三次握手才能确认双方的接收与发送能力是否正常。三次握手的作用三次握手的作用也是有好多的,多记住几个,保证不亏。也就是说,第一次第二次握手不可以携带数据,而第三次握手是可以携带数据的。在面试中,三次握手和四次挥手可以说是问的最频繁的一个知识点了,我相信大家也都看过很多关于三次握手与四次挥手的文章,今天的这篇文章,重点是围绕着面试,我们应该...

    WilsonLiu95 评论0 收藏0

发表评论

0条评论

Nino

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<