本文共 2746 字,大约阅读时间需要 9 分钟。
TCP的连接建立需要进行三次的数据交互,在结束时需要进行4次的数据交互,具体的流程图如下图所示
注意 Seq:是发送方当前报文的顺序号码 ack:是发送方期望对方在下次返回报文中给回的Seq
建立连接需要进行三次数据传输,也就是三次握手 第一次握手:客户端向服务端发送连接请求包,标志位SYN(同步序号)置为1,顺序号码为X=0。(这里为了简单的说明将初始序号设置为了0,但是在实际过程中是使用ISN(Initial Sequence Number)记性初始化的。ISN是随着时间变化的,因而每个连接都有不同的ISN。RFC793中指出ISN可看作是一个由32bit的计数器,4ms加1.这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它作出错误的解释)
第二次握手:服务端收到客户端发过来报文,由SYN=1知道客户端要求建立联机,则为这次连接分配资源。并向客户端发送一个SYN和ACK都置为1的TCP报文,设置初始顺序号码Y=0,将确认序号(ack)设置为上一次客户端发送过来的顺序号(Seq)加1,即X+1 = 0+1=1。
第三次握手:客户端收到服务端发来的包后检查确认号码(ack)是否正确,即第一次发送的Seq加1(X+1=1)。以及标志位ACK是否为1。若正确,服务端再次发送确认包,ACK标志位为1,SYN标志位为0。确认号码(ack)=Y+1=0+1=1,发送顺序号码(Seq)为X+1=1。Server收到后确认号码值与ACK=1则连接建立成功,可以传送数据了。
断开连接需要四次挥手 提醒:中断连接端可以是Client端,也可以是Server端。只要将下面两角色互换即可。 第一次挥手:客户端给服务端发送FIN报文,用来关闭客户端到服务端的数据传送。将标志位FIN和ACK置为1,顺序号码为X=1,确认号码为Z=1。意思是说”我Client端没有数据要发给你了,但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK过来。”
第二次挥手:服务端收到FIN后,发回一个ACK(标志位ACK=1),确认号码为收到的顺序号码加1,即X=X+1=2。顺序号码为收到的确认号码=Z。意思是说“你的FIN请求我收到了,但是我还没准备好,请继续你等我的消息" 这个时候客户端就进入FIN_WAIT状态,继续等待服务端的FIN报文。
第三次挥手:当服务端确定数据已发送完成,则向客户端发送FIN报文,关闭与客户端的连接。标志位FIN和ACK置为1,顺序号码为Y=1,确认号码为X=2。意思是告诉Client端“好了,我这边数据发完了,准备好关闭连接了。”
第四次挥手:客户端收到服务器发送的FIN之后,发回ACK确认(标志位ACK=1),确认号码为收到的顺序号码加1,即Y+1=2。顺序号码为收到的确认号码X=2。意思是“我Client端知道可以关闭连接了,但是我还是不相信网络,怕 Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。“(在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。)
这是由TCP的半关闭造成的。既然一个TCP连接是全双工的(数据在两个方向上能同时传输),因此每个方向必须单独地进行关闭。这个原则就是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向连接。当一端接收到一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送。发送FIN通常是应用层进行关闭的结果。 收到一个FIN只意味着在这一方向上没有数据流动。一个TCP连接在接收到一个FIN后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管应用程序能够利用这种半关闭特性,但是在实际应用过程中只有很好少的TCP应用程序这样做。
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
在TCP关闭的4次握手过程中客户端在发送完最后一个ACK响应之后进入TIME_WAIT状态。每个具体的TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)(RFC 793中指出MSL为2分钟。现实中常用值为30s,1min或2min)。他是任何报文段被丢弃潜在网络中生存的最长时间。这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。
在实际中IP数据报的TTL是基于跳数的,不是定时器。对于一个具体实现所给定的MSL置,处理的原则是:当TCP执行一个主动关闭,并发送回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可以让TCP再次发送最后一个ACK防止这个ACK丢失(另外一端超时重发最后一个FIN)。
这种2MSL等待的另外一个结果是这个TCP连接在2MSL等待时间期间,定义这个连接的插口(IP地址和端口)不能被使用,这个连接只能在2MSL结束之后才能再被使用。
在FIN_WAIT_2状态表示已经发送了FIN,并且另外一端也已经对它进行了确认。除非在实行半关闭,否则将等待另一端的应用意识到它已收到一个文件结束符说明,并向自己发送一个FIN来关闭另一个方向的连接。只有当另一端的进行完成这个关闭,才会从FIN_WAIT_2状态进入TIME_WAIT状态。响应的服务器端在接收到FIN之后进入CLOSE_WAIT状态直到应用程序关闭发送FIN,之后进入CLOSE_ACK,在收到ACK响应之后返回到起始点。