程序员人生 网站导航

TCP 的三次握手 与 四次挥手详解(转载)

栏目:互联网时间:2016-07-27 08:38:29

建立TCP需要3次握手才能建立,而断开连接则需要4次握手。全部进程以下图所示:

先来看看如何建立连接的。


首先Client端发送连接要求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段产生ACK报文,并分配资源,这样TCP连接就建立了。

那如何断开连接呢?简单的进程以下:


【注意】中断连接端可以是Client端,也能够是Server端。

假定Client端发起中断连接要求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则没必要急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告知Client端,你的要求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server真个FIN报文。当Server端肯定数据已发送完成,则向Client端发送FIN报文,"告知Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK落后入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后仍然没有收到回复,则证明Server端已正常关闭,那好,我Client端也能够关闭连接了。Ok,TCP连接就这样关闭了!

全部进程Client端所经历的状态以下:


而Server端所经历的进程以下:转载请注明:blog.csdn.net/whuslei


【注意】 在TIME_WAIT状态中,如果TCP client端最后1次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待以后连接正式关闭,并且所有的资源(包括端口号)都被释放。

【问题1】为何连接的时候是3次握手,关闭的时候却是4次握手?
答:由于当Server端收到Client真个SYN连接要求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应对的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,极可能其实不会立即关闭SOCKET,所以只能先回复1个ACK报文,告知Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能1起发送。故需要4步握手。

【问题2】为何TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,4个报文都发送终了,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后1个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。




3次握手又是甚么?

TCP是面向连接的,不管哪1方向另外一方发送数据之前,都必须先在双方之间建立1条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过3次握手进行初始化的。3次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。这就是面试中常常会被问到的TCP3次握手。只是了解TCP3次握手的概念,对你取得1份工作是没有任何帮助的,你需要去了解TCP3次握手中的1些细节。先来看图说话。alt多么清晰的1张图,固然了,也不是我画的,我也只是援用过来讲明问题了。

  1. 第1次握手:建立连接。客户端发送连接要求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
  2. 第2次握手:服务器收到SYN报文段。服务器收到客户真个SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN要求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到1个报文段(即SYN+ACK报文段)中,1并发送给客户端,此时服务器进入SYN_RECV状态;
  3. 第3次握手:客户端收到服务器SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送终了以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP3次握手。

完成了3次握手,客户端和服务器端就能够开始传送数据。以上就是TCP3次握手的整体介绍。

那4次分手呢?

当客户端和服务器通过3次握手建立了TCP连接以后,当数据传送终了,肯定是要断开TCP连接的啊。那对TCP的断开连接,这里就有了神秘的“4次分手”。

  1. 第1次分手:主机1(可使客户端,也能够是服务器端),设置Sequence NumberAcknowledgment Number,向主机2发送1个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
  2. 第2次分手:主机2收到了主机1发送的FIN报文段,向主机1回1个ACK报文段,Acknowledgment NumberSequence Number加1;主机1进入FIN_WAIT_2状态;主机2告知主机1,我“同意”你的关闭要求;
  3. 第3次分手:主机2向主机1发送FIN报文段,要求关闭连接,同时主机2进入CLOSE_WAIT状态;
  4. 第4次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后仍然没有收到回复,则证明Server端已正常关闭,那好,主机1也能够关闭连接了。

至此,TCP的4次分手就这么愉快的完成了。当你看到这里,你的头脑里会有很多的疑问,很多的不懂,感觉很混乱;没事,我们继续总结。

为何要3次握手

既然总结了TCP的3次握手,那为何非要3次呢?怎样觉得两次就能够完成了。那TCP为何非要进行3次连接呢?在谢希仁的《计算机网络》中是这样说的:

为了避免已失效的连接要求报文段突然又传送到了服务端,因此产生毛病。

在书中同时举了1个例子,以下:

“已失效的连接要求报文段”的产生在这样1种情况下:client发出的第1个连接要求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是1个早已失效的报文段。但server收到此失效的连接要求报文段后,就误认为是client再次发出的1个新的连接要求。因而就向client发出确认报文段,同意建立连接。假定不采取“3次握手”,那末只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的要求,因此不会理会server的确认,也不会向server发送数据。但server却以为新的运输连接已建立,并1直等待client发来数据。这样,server的很多资源就白白浪费掉了。采取“3次握手”的办法可以避免上述现象产生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

这就很明白了,避免了服务器真个1直等待而浪费资源。

为何要4次分手

那4次分手又是为什么呢?TCP协议是1种面向连接的、可靠的、基于字节流的运输层通讯协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已没有数据要发送了,主机1告知主机2,它的数据已全部发送终了了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告知主机1,我也没有数据要发送了,以后彼此就会愉快的中断这次TCP连接。如果要正确的理解4次分手的原理,就需要了解4次分手进程中的状态变化。

  • FIN_WAIT_1: 这个状态要好好解释1下,其实FIN_WAIT_1FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区分是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,固然在实际的正常情况下,不管对方何种情况下,都应当马上回应ACK报文,所以FIN_WAIT_1状态1般是比较难见到的,而FIN_WAIT_2状态还有经常常可以用netstat看到。(主动方)
  • FIN_WAIT_2:上面已详细解释了这类状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有1方要求close连接,但另外还告知对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
  • CLOSE_WAIT:这类状态的含义实际上是表示在等待关闭。怎样理解呢?当对方close1个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应1个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要斟酌的事情是观察你是不是还有数据发送给对方,如果没有的话,那末你也就能够 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
  • LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭1方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也便可以进入到CLOSED可用状态了。(被动方)
  • TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后便可回到CLOSED可用状态了。如果FINWAIT1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而不必经过FIN_WAIT_2状态。(主动方)
  • CLOSED: 表示连接中断

TCP协议3次握手进程分析

TCP(Transmission Control Protocol) 传输控制协议

TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采取3次握手确认建立1个连接:

位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)

Sequence number(顺序号码) Acknowledge number(确认号码)

第1次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第2次握手:主机B收到要求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包

第3次握手:主机A收到后检查ack number是不是正确,即第1次发送的seq number+1,和位码ack是不是为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

完成3次握手,主机A与主机B开始传送数据。


在TCP/IP协议中,TCP协议提供可靠的连接服务,采取3次握手建立1个连接。 
第1次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认; 
第2次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送1个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第3次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送终了,客户端和服务器进入ESTABLISHED状态,完成3次握手。 完成3次握手,客户端与服务器开始传送数据.

实例:

IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1

第1次握手:192.168.1.116发送位码syn=1,随机产生seq number=3626544836的数据包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立联机;

第2次握手:192.168.1.123收到要求后要确认联机信息,向192.168.1.116发送ack number=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;

第3次握手:192.168.1.116收到后检查ack number是不是正确,即第1次发送的seq number+1,和位码ack是不是为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功。

 

图解:
1个3次握手的进程(图1,图2)

(图1)

(图2)
 

第1次握手的标志位(图3)
我们可以看到标志位里面只有个同步位,也就是在做要求(SYN)
3 
 (图3)

第2次握手的标志位(图4)
我们可以看到标志位里面有个确认位和同步位,也就是在做应对(SYN + ACK)
4 
(图4)

第3次握手的标志位(图5)
我们可以看到标志位里面只有个确认位,也就是再做再次确认(ACK)
5 
 

TCP头部: 其中 ACK   SYN  序号  这3个部份在以下会用到,它们的介绍也在下面。


暂时需要的信息有:

ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1

SYN(SYNchronization) : 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是1个连接要求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此,  SYN置1就表示这是1个连接要求或连接接受报文。


FIN (finis)即完,终结的意思, 用来释放1个连接。当 FIN = 1 时,表明此报文段的发送方的数据已发送终了,并要求释放连接。




3次握手的进程:

首先由Client发出要求连接即 SYN=1 ACK=0  (请看头字段的介绍), TCP规定SYN=1时不能携带数据,但要消耗1个序号,因此声明自己的序号是 seq=x

然后 Server 进行回复确认,即 SYN=1 ACK=1 seq=y, ack=x+1,

再然后 Client 再进行1次确认,但不用SYN 了,这时候即为 ACK=1, seq=x+1, ack=y+1.

然后连接建立,为何要进行3次握手呢(两次确认)。



下面是释放连接的进程:



当客户A 没有东西要发送时就要释放 A 这边的连接,A会发送1个报文(没有数据),其中 FIN 设置为1,  服务器B收到后会给利用程序1个信,这时候A那边的连接已关闭,即A不再发送信息(但仍可接收信息)。  A收到B的确认落后入等待状态,等待B要求释放连接, B数据发送完成后就向A要求连接释放,也是用FIN=1 表示, 并且用 ack = u+1(如图), A收到后回复1个确认信息,并进入 TIME_WAIT 状态, 等待 2MSL 时间。

为何要等待呢?

为了这类情况: B向A发送 FIN = 1 的释放连接要求,但这个报文丢失了, A没有接到不会发送确认信息, B 超时会重传,这时候A在 WAIT_TIME 还能够接收到这个要求,这时候再回复1个确认就好了。(A收到 FIN = 1 的要求后 WAIT_TIME会重新记时)


另外服务器B存在1个保活状态,即如果A突然故障死机了,那B那边的连接资源甚么时候能释放呢?  就是保活时间到了后,B会发送探测信息, 以决定是不是释放连接。




TCP/IP协议3次握手与4次握手流程解析
 
1、TCP报文格式
  TCP/IP协议的详细信息参看《TCP/IP协议详解》3卷本。下面是TCP报文格式图:

图1 TCP报文格式
  上图中有几个字段需要重点介绍下:
  (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  (2)确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
  (3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义以下:
  (A)URG:紧急指针(urgent pointer)有效。
  (B)ACK:确认序号有效。
  (C)PSH:接收方应当尽快将这个报文交给利用层。
  (D)RST:重置连接。
  (E)SYN:发起1个新连接。
  (F)FIN:释放1个连接。

 需要注意的是:
  (A)不要将确认序号Ack与标志位中的ACK弄混了。
  (B)确认方Ack=发起方Req+1,两端配对。 

2、3次握手
  所谓3次握手(Three-Way Handshake)即建立TCP连接,就是指建立1个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这1进程由客户端履行connect来触发,全部流程以下图所示:

图2 TCP3次握手
  (1)第1次握手:Client将标志位SYN置为1,随机产生1个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
  (2)第2次握手:Server收到数据包后由标志位SYN=1知道Client要求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生1个值seq=K,并将该数据包发送给Client以确认连接要求,Server进入SYN_RCVD状态。
  (3)第3次握手:Client收到确认后,检查ack是不是为J+1,ACK是不是为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是不是为K+1,ACK是不是为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成3次握手,随后Client与Server之间可以开始传输数据了。
 
  SYN攻击:
  在3次握手进程中,Server发送SYN-ACK以后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内捏造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些捏造的SYN包将产时间占用未连接队列,致使正常的SYN要求由于队列满而被抛弃,从而引发网络梗塞乃至系统瘫痪。SYN攻击时1种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以判定遭到SYN攻击了,使用以下命令可让之现行:
  #netstat -nap | grep SYN_RECV

3、4次挥手
 3次握手耳熟能详,4次挥手估计就,所谓4次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开1个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这1进程由客户端或服务端任1方履行close来触发,全部流程以下图所示:

图3 TCP4次挥手
  由于TCP连接时全双工的,因此,每一个方向都必须要单独进行关闭,这1原则是当1方完成数据发送任务后,发送1个FIN来终止这1方向的连接,收到1个FIN只是意味着这1方向上没有数据活动了,即不会再收到数据了,但是在这个TCP连接上依然能够发送数据,直到这1方向也发送了FIN。首先进行关闭的1方将履行主动关闭,而另外一方则履行被动关闭,上图描写的即是如此。
 (1)第1次挥手:Client发送1个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
  (2)第2次挥手:Server收到FIN后,发送1个ACK给Client,确认序号为收到序号+1(与SYN相同,1个FIN占用1个序号),Server进入CLOSE_WAIT状态。
 (3)第3次挥手:Server发送1个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
  (4)第4次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送1个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成4次挥手。
  上面是1方主动关闭,另外一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程以下图:

图4 同时挥手
  流程和状态在上图中已很明了了,在此不再赘述,可以参考前面的4次挥手解析步骤。

4、附注
  关于3次握手与4次挥手通常都会有典型的面试题,在此提出供有需求的XDJM们参考:
  (1)3次握手是甚么或流程?4次握手呢?答案前面分析就是。
  (2)为何建立连接是3次握手,而关闭连接却是4次挥手呢?
  这是由于服务端在LISTEN状态下,收到建立连接要求的SYN报文后,把ACK和SYN放在1个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也能够发送1些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN1般都会分开发送。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐