tcp四次撒手

转自:http://www.cnblogs.com/cy568searchx/p/3711670.htmlhtml

因为 TCP链接是全双工的,所以每一个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的链接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP链接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另外一方执行被动关闭。
 
1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。
2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN同样,一个FIN将占用一个序号。
3)服务器B关闭与客户端A的链接,发送一个FIN给客户端A(报文段6)。
4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。
 
        状态详解:
 
        CLOSED: 这个没什么好说的了,表示初始状态。
 
  LISTEN: 这个也是很是容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,能够接受链接了。
 
   SYN_RCVD: 这个状态表示接受到了SYN报文,在正常状况下,这个状态是服务器端的 SOCKET在创建TCP链接时的三次握手会话过程当中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特地写了一个客户端测试程序,故意将三次TCP握手过程当中最后一个ACK报文不予发送。所以这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
 
  SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT链接时,它首先发送SYN报文,所以也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
 
   ESTABLISHED:这个容易理解了,表示链接已经创建了。
 
   FIN_WAIT_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状态通常是比较难见到的,而FIN_WAIT_2状态还有时经常能够用netstat看到。
   FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半链接,也即有一方要求close链接,但另外还告诉对方,我暂时还有点数据须要传送给你,稍后再关闭链接。
   TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后便可回到CLOSED可用状态了。若是FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,能够直接进入到TIME_WAIT状态,而无须通过FIN_WAIT_2状态。
  CLOSING: 这种状态比较特殊,实际状况中应该是不多见,属于一种比较罕见的例外状态。正常状况 下,当你发送FIN报文后,按理来讲是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。可是CLOSING状态表示你发送FIN报文后,并无收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么状况下会出现此种状况呢?其实细想一下,也不可贵出结论:那就是若是双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的状况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET链接。
   CLOSE_WAIT: 这种状态的含义实际上是表示在等待关闭。怎么理解呢?当对方close一个 SOCKET后发送FIN报文给本身,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正须要考虑的事情是察看你是否还有数据发送给对方,若是没有的话,那么你也就能够 close这个SOCKET,发送FIN报文给对方,也即关闭链接。因此你在CLOSE_WAIT状态下,须要完成的事情是等待你去关闭链接。
   LAST_ACK: 这个状态仍是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也便可以进入到CLOSED可用状态了。
 
 
总结:
 
1.为何创建链接协议是三次握手,而关闭链接倒是四次握手呢?
 
这是由于服务端的 LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它能够把ACK和SYN(ACK起应答做用,而SYN起同步做用)放在一个报文里来发送。但关闭链接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你全部的数据都所有发送给对方了,因此你能够未必会立刻会关闭SOCKET,也即你可能还须要发送一些数据给对方以后,再发送FIN报文给对方来表示你赞成如今能够关闭链接了,因此它这里的ACK报文和FIN报文多数状况下都是分开发送的.
 
2.为何TIME_WAIT状态还须要等2MSL后才能返回到CLOSED状态?
 
这是由于虽然双方都赞成关闭链接了,并且握手的 4个报文也都协调和发送完毕,按理能够直接回到CLOSED状态(就比如从SYN_SEND状态到ESTABLISH状态那样);可是由于咱们必需要假想网络是不可靠的,你没法保证你最后发送的ACK报文会必定被对方收到,所以对方处于LAST_ACK状态下的SOCKET可能会由于超时未收到ACK报文,而重发FIN报文,因此这个TIME_WAIT状态的做用就是用来重发可能丢失的ACK报文。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

假设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链接就这样关闭了!服务器

 


 

而Server端所经历的过程以下:网络

 

 

相关文章
相关标签/搜索