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

TCP协议中的三次握手和四次挥手图解

2016-03-25 19:23 363 查看
建立TCP需要三次握手才能建立,而断开连接则需要四次挥手。整个过程如下图所示:



建立连接:

1、C发送SYN到S,并且C进入SYN_SEND状态

2、S收到C的SYN,同时发送ACK确认包和自己的SYN包给C

3、C收到S的SYN+ACK,向服务器B发送确认ACK

数据传输开始。

断开连接:

1、客户端C发送一个FIN,用来关闭C到S的数据传送,C进入FIN_WAIT_1状态

2、S收到这个FIN后,进入CLOSE_WAIT(此时是被动关闭),然后发送ACK确认到C,这时C到S的数据链路关闭,C此时进入FIN_WAIT_2。

3、S等待发送到C的数据发送完成后,发送FIN到C,此刻S状态转换为LAST_ACK,并等待C的ACK到来。

4、C收到S的FIN,将状态转换为TIME_WAIT,并发送ACK到S,S收到ACK后,状态改变为CLOSED。

先来看看如何建立连接的。



首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

那如何断开连接呢?简单的过程如下:



【注意】中断连接端可以是Client端,也可以是Server端。

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

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

那可能有人会有疑问,在tcp连接握手时为何ACK是和SYN一起发送,这里ACK却没有和FIN一起发送呢。原因是因为tcp是全双工模式,接收到FIN时意味将没有数据再发来,但是还是可以继续发送数据。

【问题2】仅使用二次握手而不使用三次握手时,会出现什么情况?

答:假设使用的是二次握手:A给B发送一个连接请求报文段,B收到了这个报文段,并发送了确认应答报文段。那么按照二次握手的协定,B认为连接已经成功建立了,可以开始发送数据报文段。

然而,如果B发送的应答报文被丢失,那么A将无法知道B是否已经准备好,不知道B建议将什么样的序号用于B到A的传输,也不知道B是否同意A的初始序列号,A甚至怀疑B是否收到了自己的连接请求报文段,在这种情况下A认为连接还未建立成功,将丢弃B发送来的任何数据报文段,只等待接受连接确认应答报文段;而B在发出的数据报文段超时后,将重复发送同样的报文段。

于是,这样就形成了死锁。

谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: