TCP三次握手
在比较的正式的来讲描述三次握手,一般主动发起连接请求的我们习惯性叫客户端,所以上面的计算机A和计算B即为客户端和服务端,所以上图的标识即为发起第一次客户端向服务端发起建立会话请求,第二次服务回应已经收到了请求,第三次客户端回应收到可以建立连接的回应。通常我们讲两次就应该可以建立请求,在自然对话中,你要和你对话,对方回应好的,接下的时间双方就展开愉快的聊天。为什么计算需要三次,又或者为什么不是四次。这里先笼统的回答一下两次不可靠,三次为了保证可靠性,三次就可以保证可靠性,就没有必要四次或者更多次。下面我们通过解释为什么需要是三次握手来记忆和分析。
我们需要明白的是TCP协议是全双工的可靠的协议。我的理解是这样子,既然是双工,双方计算计算都需要可读(发)可写(收),类比于自然对话,我们可以简单的这么认为:嘴巴=发,耳朵=收。自然对话中我们需要确认双方都有对话的能力,且双方都知道自己的能力,
①A同学说B同学我要和你发起一轮对话,该次是试探性看AB有没有对话的可能,A能发起请对话仅仅代表A的嘴巴的是正常,但是A对于B还一无所知。
②B同学回应A同学说我同意和你发起对话,该次表示B的耳朵是正常,接收到信息了,同时B知道A嘴巴正常,A知道B的耳朵正常,A也知道B嘴巴正常。但是B不知道A的耳朵是否正常,此时建立对话,A并不可靠。
③A回应B说B我已经准备好和你对话了,B收到该信息终于知道A的耳朵是正常,好吧我这边也可以就绪了。
通过上面的样例我们已经很清楚的知道A、B都是可收可发的,这样子才算可靠。当然在我理解来讲,为什么客户端不一次性告诉服务端可收可发情况都正常,服务端准备好资源建立连接,一起反馈客户端信息服务端可收可发,客户端准备好资源建立连接。这样子不就只有两次了吗。我认为有以下的原因:
a.我们要知道在复杂的网络环境中其实双方都无法确认自己的信息是可达的,另外TCP是全双工,此时服务端也无法知道客户端是否收到自己的Seq值,在这种情况下如果服务器有消息要发送给客户端,假设是对齐信息是和数据分开发送,客户端如果先收到数据后收到对齐信息则无法处理,对齐信息和数据一起发送,如果客户端无法接收则存在资源浪费,所以必不能这样子设计,分开发送的对齐信息和数据也是比较合理的,避免数据先到无法处理的情况,同时也可以在一定程度上减少SYN洪流的影响。
b.网络通信世界存在短时间内多次会话,客户端的端口存在复用,TCP协议是个五元组=ip+端口+协议+ip+端口,如果第一次握手客户端发送的SYN信息由于某些原因延迟,客户端由于没有收到服务端的ACK,放弃该次会话请求,此时如果服务还要准备资源的明显存在资源浪费。
c.网上比较多的解释为什么要三次握手,我理解也有一定合理性。
三次握手 主要是为了防止已失效的连接请求报文段突然有传送到了B,因而产生错误。
“已失效的连接请求报文段”是指A发出连接请求,但因连接请求报文丢失二位收到确认。 于是A再重传一次连接请求。后收到连接请求确认,建立连接。数据传送完毕后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。没有”已失效的连接请求报文段“。
现在假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误以为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。
由于现在A并没有发出建立连接的请求,因此不会理财B的确认,也不会向B发送数据。但B确以为新的运输连接已经建立了,并一直等待A发来数据。B的许多资源就这样白白浪费了。
采用三次握手的办法可以防止上述现象的发生。
总结:三次握手比较合理,网络通信环境太复杂,这样子减少一些资源浪费,降低一些恶意影响,同时用较少的次数确认了机器和网络的信息,所以这样子设计还是相对合理的。
写给自己:感觉第三次握手中发送的ack的时候是可以一起发送数据的,因为双方的对齐信息和状态都已经同步了,但是实际设计中服务端是没有准备好,好像发了也没有用。