您的位置:首页 > 理论基础 > 计算机网络

TCP的三次握手和四次挥手详解

2016-07-30 12:30 246 查看
          TCP协议的三次握手和四次挥手是常考的面试题。在此我们来分析一下其过程。

          当谈到TCP协议的三次握手和挥手时,可以理解那时客户端和服务器端的建立连接和解除连接的过程。

 
一、TCP的概念:

         TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协
议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。用户数据报议,(UDP)是同一层内,另一个重要的传输协议。在因特网协议族(Internet
protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。

      tcp协议首部:

        


二、TCP的三次握手

        先来看看三次握手的流程:以下标出来的就是所谓的三次。

        


  我们来详细的来分析一下其三次的过程:

         第一次:首先客户端发送连接请求报文段,将
SYN
位置为1,seq(
Sequence
Number)
为x;然后,客户端进入
SYN_SEND
状态,等待服务器的确认;SYN
(同步序列编号);

         第二次:当服务器收到客户端的
SYN
报文段,需要对这个
SYN
报文段进行确认,设置Ack确认帧为x+1即为客户端发来的(seq+1);同时,自己自己还要发送
SYN
请求信息,将
SYN
位置为1,
Seq
为y;服务器端将上述所有信息放到一个报文段(即
SYN+ACK
报文段)中,一并发送给客户端,此时服务器进入
SYN_RECV
状态;

 
       第三次:当客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手;

三、TCP的四次挥手

 
      tcp四次挥手,由于TCP连接是全双工的,因此每个方向都必须单独进行关闭;

 
     我们来看看上图中所标出的四次过程;可以模拟为下面的场景:

 
 




         第一次:主机1(可以使客户端,也可以是服务器端),向主机2发送一个
FIN
报文段;此时,主机1进入
FIN_WAIT_1等待
状态;这表示主机1没有数据要发送给主机2了;

 
       第二次:主机2收到了主机1发送的
FIN
报文段,向主机1回一个
ACK
报文段,主机1进入
FIN_WAIT_2等待
状态;主机2告诉主机1,我“同意”你的关闭请求;

 
       第三次:主机2向主机1发送
FIN
报文段,请求关闭连接,同时主机2进入
CLOSE_WAIT
状态;

 
       第四次:主机1收到主机2发送的
FIN
报文段,向主机2发送
ACK
报文段,然后主机1进入
TIME_WAIT
状态;主机2收到主机1的
ACK
报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

 
    

 
       如果还不理解四次挥手的过程,那么看下面一段:

 
        1、client向Server发送消息 FIN“我没有数据要发给你了,我要结束”;

 
        2、Server收到client发来的消息,向主机1回复 ACK“你的消息我收到了,但是我还没准备好,你等我消息吧”这个时候client就进入FIN_WAIT状态,继续等待Server端的FIN报文。

 
        3、当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。

 
         4、Client端收到FIN报文后,"知道可以关闭连接了,但是还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,Client端也可以关闭连接了。TCP连接就这样关闭了!

 问题:  
1、主动发起关闭连接的操作的一方将达到TIME_WAIT(即上图的计时等待)状态,而且这个状态要保持
Maximum Segment Lifetime的两倍时间。为什么要这样做而不是直接进入CLOSED状态?
原因有二:

       一、保证TCP协议的全双工连接能够可靠关闭;
       二、保证这次连接的重复数据段从网络中消失;
先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到
Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与
重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这
样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入
CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的
连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是
还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在
网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协
议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的
新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有
数据都从网络中消失。
2、为什么连接的时候是三次握手,关闭的时候却是四次握手?
     因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息