TCP建链为何一定要三次握手?

来源:互联网 发布:人体工学椅 知乎 编辑:程序博客网 时间:2024/06/03 13:15

【来源】:http://www.meilei007.cn/tcp_three_handshake_reason/ 

看了一些网上的解答,都不是很清楚,这里说一下我的理解。



首先说明为什么不能是两次握手,因为三次握手能够防止已过期的数据报被再次传到被连接主机。
举个例子,假设只需要两次握手连接就能够建立,那么客户端A往服务器端B发送连接数据报SYN,服务器端B没有收到该数据报,A又发送了第二个数据报SYN到B,B这次正常收到,返回ACK,A收到ACK,连接建立。数据传输完,连接断掉了之后,第一次发送的数据报SYN突然又到达了B,B会认为这是A发送的新的一次连接请求,返回一个ACK给A,这个时候,B认为连接建立,但是A收到一个莫名的ACK数据报,不会做任何处理。B就一直等在那里,等着A发送数据。


还有一种情况是两次握手可能发生的,举个例子,A发送给B大量的连接请求,B收到了,回复ACK的时候A却没收到,但是B不管,B认为已经建链成功了,开始往A发数据,但是A没有收到ACK,认为链接没建立,就会无视B的数据,一直等ACK,这样,就形成了死锁,B因为收不到A返回的数据ACK,会一直不断重发数据,A收不到B的建链ACK,会一直等待不接受数据。


那为什么不是四次握手呢?这里是因为服务器端在回ACK消息的时候,在同一个数据报里面,加上了自己的SYN数据,所以把这两个数据装在了同一个数据报里面。


那么在拆链的时候为何必须是四次呢?
这里要弄明白一点,TCP的数据传输是全双工的,单方面拆链并不影响对方向自己发送数据。因此,A发送FIN包给对方,表示我这边没有数据了,对方再回复ACK,表示不会再接受A发来的数据。B再发FIN包给A,A回ACK表示,“ok,我知道你也没数据发送了,我们连接关闭吧”。至此,TCP才是在两边真正断掉。当然,如果A发送FIN包给B,告诉B,我这边没数据的同时,B也没有数据发送了,那么B其实是可以在一个数据包里面把ACK和FIN包都发给A的,这样,其实三次也能把链接关掉。只不过传统的协议都是按照四次来实现的,就当做一个美好的传统来看待就好了,至少程序员写协议栈的时候更轻松了:)


三次握手建链:



















四次握手拆链:



0 0