zweizhao.github.io

项目,文章,随笔,博客,Markdown,个人网站,人生感悟。

View on GitHub

三次握手

关于三次握手,算是面试中比较常见的HTTP方面问题了。

事实上,相信绝大多数接触过的人都了解或有印象“三次握手”。

但是,会不会老是记不住具体是什么,顺序怎样。那一大坨英文简写又是什么东西。

下面我们就通俗易懂的记下这个玩意儿,从逻辑上彻底理解,也就不会再怕面试官了。

理解

本质上来说,三次握手是一种验证机制,算是一种协议方式。我们把这种协议方式放到实际场景中,你就能理解了。

比如,现在是二战中,假设有这么个场景:

A:请求联络,这里是A,需要弹药急速增援。

联络失败

没有对应的回应(响应)对象,所以没人知道这个是联系谁,联络失败,没问题吧。

这里是请求弹药,如果是发送战报,你觉得会怎样?你敢在战场玩广播吗?

再来:

此时连线已经确认对象是B,本文不考虑被拦截的情况。

A:请求联络,这里是A,需要弹药急速增援,听到请回答。

B:……

A:请求联络,这里是A,需要弹药急速增援,听到请回答。

B:……

联络失败

对象无响应,联络失败,没问题吧?

再来:

A:请求联络,这里是A,需要弹药急速增援,听到请回答。

B:B已收到,弹药立马发送,听到请回答。

B:B已收到,弹药立马发送,听到请回答。

联络失败

A没收到,因此也B不知道A有没有收到信息,所以联络失败,有没有问题?

再来:

A:请求联络,这里是A,需要弹药急速增援,听到请回答。

B:B已收到,弹药立马发送,听到请回答。

A:(确定整个流程通了,A已收到,但不响应。)

B:B已收到,弹药立马发送,你他娘的听到没,听到请回答。

A:(确定整个流程通了,A已收到,但不响应。)

……

联络失败

好了,问题就更多就出现这里,实际上还算是联络失败,为什么?

问题就是,此时B已经发送了消息,并且A也收到了(A知道流程没问题),但是B并不知道A收到了(B不知道整个流程是不是通了),所以B有可能会多次发送确认A收到,或者干脆几次后断开联络,那么就更不知道A有没有收到了。

最后,逻辑成立的情况:

A:请求联络,这里是A,需要弹药急速增援,听到请回答。

B:B已收到,弹药立马发送,听到请回答。

A:A已收到(确定整个流程通了)。

B:(确定整个流程通了。)

联络成功

这里A第一次联系,B响应联系,A再次响应联系,共三次,所以叫三次握手。

三次之后,基本确定,联络成功,如果随后就有其他的消息,就可以建立在当前的联络上(比如真正的网络传输,需要先确认客户端与服务端能搭上,才能正确传输数据)。


解析

再次之前,说几个与三次握手有关的名词:

名词 释义
SYN synchronous 建立联机
ACK acknowledgement 确认
seq Sequence number 顺序号码
ack Acknowledge number 确认号码
established 已连接
SYN_SENT 发送待确认
SYN_RCVD 半连接

模拟上述消息:

客户端:SYN、seq=100

建立联机(进入发送待确认状态,SYN_SENT),发送个顺序号码给对方确认,确认逻辑是:确认码 = 顺序码 + 1。

服务端:SYN、ACK、ack=101,seq=200

建立联机(进入半连接状态,SYN_RCVD),确认收到、确认码 101(来自100 + 1),顺序码 200。

客户端:ACK,ack=201

确认收到(进入已连接状态,established ),确认码 201。

服务端:(done)

搞定(进入已连接状态,established )。

图形理解如下:

title: 三次握手
客户端 -> 服务端: SYN、seq=100
服务端 -> 客户端: SYN、ACK、ack=101,seq=200
客户端 -> 服务端: ACK,ack=201