ok,首先我们说一下TCP的三次握手。
第一次握手:建立连接时,客户端 发送 syn 包(syn=j)到 服务器,并进入 SYN_SENT 状态,等待服务器确认;
syn:同步序列号(Synchronize Sequence Numbers)
第二次握手:服务器 收到 客户端 发送的 syn 包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即 SYN+ACK包,此时服务器进入 SYN_RECV 状态;
seq: (sequence)
ack: 确认
先说下为什么加1?
假设 a 邮了一个快递给 b,快递员是 c(快递员不会写字),a 想知道 b 是否接收到了快递,然后 b 就把快递又邮回去了。但是 a 懵逼了,因为它不知道是不是快递员自己送回来的还是 b 送过来的。所以 b 加了一个1,表示自己收到了。
然后为什么又发了一个序列号?(seq)
因为 b 也想确认我返回的快递是不是被快递员 c 送到 a 手里了。
第三次握手:客户端 收到 服务器 的 SYN+ACK 包,向 服务器 发送确认包 ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP连接成功)状态,完成三次握手。
established: 建立成功了
*******************************************************************************************************************************
ok, 接下来说为啥需要三次,而不是两次!
我相信很多同学看完别人的解释还是会懵逼。因为我之前和你们一样(可能不一样,或许我太笨)
疑问?怪了 都说问题出在丢包,难道established之后就不会丢包了吗? 这到底什么意思!
ps: ok? 如果有这个疑问的看我的文章应该是能看懂的。没有疑问的同学看了上边的就可以撤了,上边说的也很详细,或许上边看完你就懂了
好,为啥需要三次握手呢?
那么还是上边那个送快递的例子!稍作修改
a 要把自己的孩子送到 b 家里待几天。a 要通过给 b 送快递的方式来确定 b 在不在家(假设没有电话),c 是快递员。
这中间有个问题,首先,c 还是那个不会写字的快递员。
然后 a 的快递送给 b 的时候,c 走的是高速,大家都知道高速是单行道的吧!(不知道的话,我现在告诉你)
那么 b 的快递送给 a 的时候,假设没有高速,所以 c 只能走很烂的土路。
那么问题就在这里,假设只有两次握手。 a的快递送给b, b收到后,要传给a
但是,b 的快递给 a 的时候呢, 快递员 c 因为走得路太烂了,导致花了4天时间。
此时,a 在等 b 快递的时候定了一个时间2天,但是因为快递员 c 2天后没来,所以 a 以为b不在家,把门关了。之后 a 又 发了一个快递确认 b 在不在家。
后来,快递员 c 4天后来到 a 这里发现门都关了导致任务失败了。
但是 b 呢? b 已经准备好 a 的孩子来家里玩了,就打开门傻傻的一直在等。因为它不知道 快递员 c 没有完成任务。
过一会 b 又会收到第二个快递,那么 b 会再打开一个门等孩子。(它并不知道都是a发过来的)
好了。到这里,大家把a当成客户端,b当成服务器端再捋一下就Ok了!
这里的路大家就当是遇到了种种问题或者网络不行吧!
OK, 那么接下来说3次握手之后会有其他问题吗?
如果有第3次握手,也就是说 b 给 a 发了包裹之后,等 a 的通知, 如果 a 没返回包,那么 b 过几天也把门关了。(两次握手的话,b 发过去不用等 a 的回复)
说明两边门都关掉了。自然 a 会再次发送另一个快递,看看路是不是通了或者b在不在家。
假设一切顺利,那么 a 就知道了 他家到 b 家的路没有问题, b 也知道了 自己家到 a 家的路也没有问题!
当然,接下来把孩子送过去就Ok了。是不是有人还想问 孩子送到半路出了问题怎么办!(当然,路都通了,这种问题几乎不存在。)假设真的出了问题。那么 2 天后,b 没有回应。说明失败了,那么就相当于失败了。(你问我孩子咋啦?我不知道。)
那么,又有什么问题呢?a和b 知道路是通的, b 只会打开一个门等孩子,就算是失败了,a 至少不用发快递问 b 在不在家了。所以它只需要再发一个孩子过去,直到孩子发过去为止。
总结:3次握手是为了减少因网络或其他原因造成不必要的资源浪费(b开了无数的门等孩子,b很累)