TCP通讯的三次握手和四次撒手的详细流程(顿悟)

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

三次握手网络

TCP是主机对主机层的传输控制协议,提供可靠的链接服务,采用三次握手确认创建一个链接:并发

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

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

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

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

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则链接创建成功。blog

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


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

实例:

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

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

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

第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则链接创建成功。

 

图解:
一个三次握手的过程(图1,图2)

 

(图1)

(图2)
 

 

第一次握手的标志位(图3)
咱们能够看到标志位里面只有个同步位,也就是在作请求(SYN)
3 
 (图3)

第二次握手的标志位(图4)
咱们能够看到标志位里面有个确认位和同步位,也就是在作应答(SYN + ACK)
4 
(图4)

第三次握手的标志位(图5)
咱们能够看到标志位里面只有个确认位,也就是再作再次确认(ACK)
5 
 
(图5)

一个完整的三次握手也就是 请求---应答---再次确认

四次分手:
 
因为 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报文的建连请求后,它能够把 ACKSYNACK起应答做用,而 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报文。
相关文章
相关标签/搜索