建立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报文。
TCP是面向连接的,不管哪1方向另外一方发送数据之前,都必须先在双方之间建立1条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过3次握手进行初始化的。3次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。这就是面试中常常会被问到的TCP3次握手。只是了解TCP3次握手的概念,对你取得1份工作是没有任何帮助的,你需要去了解TCP3次握手中的1些细节。先来看图说话。多么清晰的1张图,固然了,也不是我画的,我也只是援用过来讲明问题了。
SYN
位置为1,Sequence
Number
为x;然后,客户端进入SYN_SEND
状态,等待服务器的确认;SYN
报文段。服务器收到客户真个SYN
报文段,需要对这个SYN
报文段进行确认,设置Acknowledgment
Number
为x+1(Sequence Number
+1);同时,自己自己还要发送SYN
要求信息,将SYN
位置为1,Sequence
Number
为y;服务器端将上述所有信息放到1个报文段(即SYN+ACK
报文段)中,1并发送给客户端,此时服务器进入SYN_RECV
状态;SYN+ACK
报文段。然后将Acknowledgment
Number
设置为y+1,向服务器发送ACK
报文段,这个报文段发送终了以后,客户端和服务器端都进入ESTABLISHED
状态,完成TCP3次握手。
完成了3次握手,客户端和服务器端就能够开始传送数据。以上就是TCP3次握手的整体介绍。
当客户端和服务器通过3次握手建立了TCP连接以后,当数据传送终了,肯定是要断开TCP连接的啊。那对TCP的断开连接,这里就有了神秘的“4次分手”。
Sequence Number
和Acknowledgment
Number
,向主机2发送1个FIN
报文段;此时,主机1进入FIN_WAIT_1
状态;这表示主机1没有数据要发送给主机2了;FIN
报文段,向主机1回1个ACK
报文段,Acknowledgment
Number
为Sequence Number
加1;主机1进入FIN_WAIT_2
状态;主机2告知主机1,我“同意”你的关闭要求;FIN
报文段,要求关闭连接,同时主机2进入CLOSE_WAIT
状态;FIN
报文段,向主机2发送ACK
报文段,然后主机1进入TIME_WAIT
状态;主机2收到主机1的ACK
报文段以后,就关闭连接;此时,主机1等待2MSL后仍然没有收到回复,则证明Server端已正常关闭,那好,主机1也能够关闭连接了。
至此,TCP的4次分手就这么愉快的完成了。当你看到这里,你的头脑里会有很多的疑问,很多的不懂,感觉很混乱;没事,我们继续总结。
既然总结了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次分手又是为什么呢?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_1
和FIN_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(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)
第2次握手的标志位(图4)
我们可以看到标志位里面有个确认位和同步位,也就是在做应对(SYN + ACK)
(图4)
第3次握手的标志位(图5)
我们可以看到标志位里面只有个确认位,也就是再做再次确认(ACK)
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会发送探测信息, 以决定是不是释放连接。