TCP连接和断开 “三次握手和四次挥手”

来源:互联网 发布:cgi加载java class 编辑:程序博客网 时间:2024/06/04 19:02

    今天看《分布式系统概念与设计》第四章进程间通信,涉及UDP数据报通信、TCP流通信两种传输层的通信协议,特别是TCP细节相对较多,现主要对TCP的连接和断开过程进行分析。

一、TCP流通信协议的概念

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。

应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

    TCP的首部,一些字段会在后面用到。


二、TCP连接的建立

    TCP建立连接需要3次握手。


    第一次握手:主机A发送位码为SYN=1,随机产生Seq number=x的数据包到服务器,客户端进入SYN_SEND状态,等待服务器的确认;主机B由SYN=1知道,A要求建立联机;

    第二次握手:主机B收到请求后要确认联机信息,向A发送Ack number(主机A的seq+1),syn=1,随机产生Seq=y的包,此时服务器进入SYN_RECV状态;(其实,这一次握手完成了两项操作,也可以说是两次握手的合并:第一是回应A的连接请求,ACK number=x+1;第二是主动发起一次信息连接,目的是确认自己能收到对方的信息,那么对方可以收到我发的信息吗?因为信息交流通道是双向的,必须保证双方发送的消息,彼此都能收到。其方式与A发起的方式是一致的,发送位码为SYN=1,随机产生Seq number=y的数据包到A)

    第三次握手:主机A收到后检查Ack number是否正确,即第一次发送的x+1,若正确,主机A会再发送Ack number(主机B的y+1),主机B收到后确认seq值则连接建立成功。客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

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

三、TCP连接的断开

       TCP关闭连接需要4次挥手。


    第一次挥手:主机A(可以使客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number(由之前通信过程确定,不像建立连接时是随机的),向主机B发送一个FIN报文段;此时,主机A进入FIN_WAIT_1状态;这表示主机A没有数据要发送给主机B了;

    第二次挥手:主机B收到了主机A发送的FIN报文段,向主机A回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机A关闭了发送,进入FIN_WAIT_2状态;

但是如果B还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据。所以不像连接过程中第二次握手那样,除了发送确认信息,还发送了其他功能信息。

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

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

下面是对这一过程的通俗解释:点击打开链接

    假设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连接就这样关闭了!

四、为何是“3次握手 4次挥手”

    对TCP连接和断开的过程的理解,一定要抓住一点,就是TCP是全双工的(TCP通信的两端都具有发送和接收两个功能,都需要独立考察),不要将视角局限在发起连接和断开的一方,要兼顾通信的双方。比如连接过程,A向B发起连接,那么站在A的视角来看这个过程,发送一个信息给B,如果接到B的确认信息,那么对A来说,连接过程就成功了;但是站在B的角度来看这一过程,我把信息发给A,A有没有收到呢?(B能接到A的发送的信息,并不能断定A就一定能接到B的信息,因为通信的一端发送和接收是两个独立的功能模块)所以,A要返回一个消息给B,完成这一步,B也就确认跟A的连接成功了。至此,通信的双方都确定完成了连接,整个过程才真正成功。对于断开过程,由于同样的道理,其实跟连接的过程是很相像的,但是由于存在半关闭的状态(也就是一端关闭了发送功能,另一端还会发送;因为虽然一端没有数据发给另一端了,但是另一端还有数据发送,不想关闭),所以没有办法像连接过程一样,将两次握手合并为单独的一次握手,这也是为什么“3次握手 4次挥手”存在的原因。

原创粉丝点击