为什么握手需要三次而不是四次?
记场景就知道为什么需要三次握手而不需要四次握手了。
场景:客户端发起一个连接请求,syn=1后自己宕机,这个请求恰好由于网络原因没有马上到达服务端。客户端重启后,重新发送一个请求syn=2,但此时服务端恰好收到syn=1的请求,然后返回ack=1。
假如只需要两次握手,那么服务端在发出ack=1的时候就进入了连接状态,这时候客户端开到服务端返回的是ack1而不是ack2,没有达成统一,所以不能建立连接。但是服务器已经进入连接状态了,在客户端发现不对的时候,需要把服务器从连接状态中扯出来(销毁历史连接),这势必会浪费资源。
如果是三次握手,那么客户端在接收到服务器返回的ack1的时候,就能阻止服务器进入连接(发送rst而不是继续握手)。
为什么握手需要三次而不是四次?
说是四次也行。顺序分别是:
- 客户端->服务器:请求连接
- 服务器->客户端:收到你的连接请求
- 服务器->客户端:为了同步序列号,我需要你从syn=xxx开始发起
- 客户端->服务器:收到,我就从syn=xxx开始发,这是syn=xxx的数据
其中第二步和第三步可以合成一步,所以是三步。有人会问为什么四次挥手的顺序也是1 2 2 1,为什么挥手就要四次而握手的四次就可以合并成三步?是因为服务器发送的第二步和第三步不是同时发出来的,中间还有一段间隔用来做事情,后面细说。
为什么三次握手能同步序列号?不能两次吗?
四次握手的顺序是1 2 2 1,前面的1 2只是客户端告诉服务端我需要你从序列号为多少的地方开始发,而服务端想要客户端什么地方开始的数据还是没有告诉客户端。所以服务器知道客户端的心意后,也需要向客户端表明他的心意。两次握手的话就只是客户端向服务器表露心意,客户端不知道服务器的心意。
**客户端发出的第三次握手丢了怎么办? **
假如客户端第三次握手发的ack丢了,客户端已经进入了连接状态,服务器还在即将连接态,也无所谓。不管是谁想跟对方聊情侣之间才能聊的话题,都有解决方案。
- 如果服务器想跟客户端聊情侣之间的话题,但他清楚他和客户端并没有正式确定关系(没有建立tcp连接),他就会持续周期性的超时重传ack+syn,想要与客户端确定关系。
- 如果客户端想跟服务器聊正文的话,照样发正文,(正文包括ack+想说的话),当服务器接收到正文里面的ack的话,会自动进入连接状态。
四次挥手
为什么挥手需要四次而不是三次?
四次挥手的顺序也是1 2 2 1。
- 客户端->服务器:FIN
- 服务器->客户端:ACK
- 服务器->客户端:FIN
- 客户端->服务器:ACK
为什么需要四次?
2 3不能合成一步。因为客户端向服务器发送的FIN意思是客户端不想说话了,不意味着服务器不想说话了。所以服务器在收到客户端的FIN的时候,会先对这个FIN回复。然后若是服务器有没有处理完的消息或者是还有未说完的话,就不能对客户端说我要结束了(不能昧着良心)。等处理完了再对客户端FIN。