一、TCP三次握手过程
首先我们回顾下tcp三次握手过程
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=X ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=X+1,同时也要为自己初始化一个序列号 seq=Y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=Y+1,自己的序列号seq=X+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
二、TCP三次握手形象解释
tcp连接建立后,双方就处于全双工通信状态下了,什么是全双工?可以理解为客户端a和服务端b之间搭了两根管道(管道的数据流是单向的,同一时刻只能由一端来发送数据,大家可以脑补下操作系统的进程间管道通信方式,是不是跟这个很像?),
这两个管道分别用来发送和接收数据,比如针对客户端a而言,管道1用作发送数据,管道2用作接收数据,那从服务端b的角度来讲,管道1就是用作接收数据的,管道2用作发送数据的。
为了保证tcp连接的可靠性,必须满足下面四个条件:
1、客户端a已确认自己到服务端b的管道是通的
2、客户端a已确认服务端b到自己的管道是通的
3、服务端b已确认自己到客户端a的管道是通的
4、服务端b已确认客户端a到自己的管道是通的
这四个条件成立后,tcp通信双方都已确认自己到对方的管道是通的(发送数据),并且对方到自己的管道也是通的(接收数据),就可以放心通信了。
下面来看三次握手,第一次握手完毕后,服务端b收到客户端a的消息,但此时客户端a并不知道自己发的消息是否被服务端b收到了,所以本次握手只成立了条件4。
同理,第二次握手完毕后,条件1、条件2都成立了,此时服务端b并不知道自己发的消息是否被客户端a收到了,所以需要第三次握手。
第三次握手完毕后,条件3成立。至此,上述4个条件都已成立,tcp可靠连接建立完毕。
看到这里相信大家会明白为什么tcp不是2次握手或4次握手了吧?一句话总结,2次不够、4次多余
补充
为什么管道是单向的,同一时刻只能由一端来发送数据?可以这样理解,把数据看做一个乒乓球,这根管道的直径是这个乒乓球的大小,那同一时刻只能由一端来传输‘乒乓球’,两端同时传输就会发送碰撞,数据传输就会出现问题(这个和数据链路层的介质访问控制子层有点类似,只不过mac子层是基于广播式网络,属于多对多,咱们这里的管道是端到端,属于一对一,并且mac子层对发生碰撞的处理也有更多灵活的方式实现,比如csma/cd、csma/ca等)
本篇文章形象地解释了tcp三次握手和一些相关概念,只是为了帮助大家理解这些内容,描述的地方可能有的不够精确、详细,有任何问题欢迎评论区交流。
参考链接:https://blog.csdn.net/qzcsu/article/details/72861891