为什么要握手
数据在传输方向上分类有三种
- 单工
只支持数据向一个方向传输。场景:广播、电视 - 半双工
支持数据双向传输,但是在同一时间只能向一个方向传输。场景:对讲机 - 全双工
支持同一时间双向传输。场景:电话
TCP属于全双工分类,但是在传输数据之前,必须确定通信的两端(客户端和服务端)都是可以正常连接的,所以就需要握手
握手的过程和状态
在握手开始之前,客户端的状态为close状态,服务端的状态为listen状态
- 第一次握手发生在客户端,客户端向服务端发送一个数据包,包含两个信息:SYN=1(请求连接) 和 Seq=12345(序列号,为随机数字),发送完成后,客户端状态由close变为SYN_SENT
- 第二次握手发生在服务端,服务端接受了数据包
首先检查是否有SYN,发现SYN=1,知道这是一个请求连接请求,服务端就需要发送一个应答ACK=1,并提供应答序号,它的值就为客户端发送的Seq+1,即Ack=12346
然后检查自己是否有多余的资源可以连接,如果可以,就将在这个应答包中再添加一个SYN=1,告诉客户端我这没有问题,我也请求连接,并发送一个请求序号Seq=789(随机数字)
最后服务端的状态由listen状态变为SYN_RECV状态 - 第三次握手发生在客户端,客户端接收了数据包
首先ACK=1,表明这是个应答包,则检查Ack的序号是否为刚才的Seq+1,检查无误
然后看下SYN=1,表明服务端也在请求连接,则根据服务端发送过来的Seq做一个应答Ack,发送ACK=1, Ack=790(即789+1,服务端的请求序号+1)
握手完成客户端状态有SYN_SENT转变为ESTABLISH - 服务端收到应答后,检查无误后,将自己的状态由SYN_RECV转为ESTABLISH
至此,三次握手完成,我们也可以将三次握手认为是三次的数据传输
为什么是三次
- 为什么不是一次
一次只能是客户端发起,将数据发送到服务端
客户端无法知道服务端的状态,不能确定是否可以通信 - 为什么不是两次
第一次客户端将数据由客户端发送给服务端,服务端能知道客户端是可以连接了
第二次服务端应答客户端,并为此申请一个连接资源等待连接
第二次握手,客户端能知道服务端是能接收到客户端的请求的,可是服务端并不知道客户端是否能接收到服务端的请求。 - 三次握手 可以确保双方都能确定对方能接受到请求,并能接受到正确的请求,就可以确定这是一个安全的可信的连接