tcp协议还是在读书时学计算机网络接触到的,那天看脉脉上有人提前这个老生常谈的问题,顺带回忆了一下,也不需要死记硬背,理解就行啦哈哈哈😃。
---------------------华丽的分割线--------------------
tcp报文头部有序号,确认序号,ACK,SYN等控制位。来看看通信时的情况,我比较喜欢把双方简化成a,b两节点,来看看它们之间的通信交互过程:
①第1条消息:
a节点发起连接请求,你想,咋样才能表示它是请求报文,不就是把SYN这个控制位置上标志(双方约定好),对方才能识别到这个报文到底是个啥嘛,所以得把SYN置1带上吧,有了这个也不行吧,你看报文头部还有个序号,至少你得向别人传递你这条消息的顺序,所以有个seq序号,所以这条消息是SYN=1, seqa。
②第2条消息:
b节点收到a发过来的这条消息,额,发现控制位SYN置1,哦,原来是请求报文,那我需要回复a节点确认;把确认的控制位ACK置1(对方才知道这条消息是确认报文嘛),然后再把确认序号ack弄上(这里值协议是seqa+1,试下为啥+1,这就是告诉对方你的报文我收到啦,你下次接着发seq+1的,按这逻辑能说通,本来你下次就应该发seq+1的;那为啥不可以ack=seq,我的理解是可以的,只不过协议制定者这样规定而已,要是规定ack=seq,对方接受到了它也能知道,额我发的报文别人收到了,但此时自己发下一条报文时需要注意进行加的操作了;只要双方约定好了,其实都可以达到这个效果的,没办法,目前协议就这样规定)。本来走到这里,回复a的报文需要填的字段就完了,但是,你想,既然双方要通信,是不是b点也要发请求给a节点,那此时如果b点把自身请求和对a的确认回复合成一条报文,那岂不是节省了控制开销和提高通信效率?且这根据这些控制位一条报文也是能表达这个效果的,这就是我们协议中一个小小的机制,叫做“捎带确认”,当然,有些人做协议创新的时候还会在保留字段上做文章,其实,中心思想就是这个捎带确认。那此时第2条消息就是回复a节点的请求ACK=1,ack=seqa+1,加上b节点自身的请求SYN=1,seqb。
③第3条消息:
a节点收到b节点发的消息后,知道自己发的请求报文b收到了,同时b节点也在和自己请求连接,那此时得回复b节点的请求吧,那此时得把确认控制位ACK置1吧,确认序号也必须加上吧ack=seqb+1(意思就是b节点你的请求我收到啦,下次你发报文序列号应该是seqb+1啦);注意此时还没有完,a节点发这个确认报文得消耗一个序号吧,那该多少呢,就是上次b节点告诉a节点你下次应该发的序号值啦,所以还要有seqa=seqa+1;所以最后是ACK=1,ack=seqb+1,加上seqa=seqa+1。
④那双方连接过程已完毕,此时经常有人问你,2次握手行不行,4次,5次等等行不行❓
那我的理解是,2次不行,其他次数都行(但3次最好,效率高控制开销小)。为啥2次不行,那书上很多都是解释的是第1条消息在中间耽搁了的情形,的确是这个道理;但是我从通信的角度理解,试想,既然是双向通信,两边都应该知根知底,我得知道自己和对方通信发送和接收正常不正常。通过第1,2消息,a节点可以推出:自己发送、接收消息没问题(我都收到b节点的确认消息了,说明我接收没问题,同时我发的请求它收到了才会给我确认,那我发送也没问题)和对方b节点发送、接收没问题(都给我发确认了,b发送没问题,同时b收到了我的请求消息它才会发确认,说明它b接收也没问题);但此时b节点仅通过第1,2消息,只能推出,a节点发送没问题,和自己接收没问题,推不出a节点接收和自己发送有没有问题,那此时有了第3条消息,那此时b节点也能知道a和自己发送和接收是不是正常的了。
为啥不是4次,5次等等握手呢❓其实可以的,只不过没必要,我学协议的时候,我导师给我说过,通信的过程永远是不可靠的,即使你前期通过各种预测呀握手啊这些判断了,但真正下一次通信的那个点那个时候是否绝对可靠是不确定的。那既然通过越多的握手达到的效果和3次握手一样,同时4,5次握手还带来了控开销和降低通信效率,那选3次岂不美滋滋😋。就像网友调侃说的,待会儿规定需要4次握手,你又会问那为啥不可以5,6,……999次,哈哈哈,最后你总得让我选个次吧🙃。
纯手机码,码字太累了🦆