1.1.1 *三次握手和四次挥手*
TCP 三次握手就好比两个人在街上隔着50米看见了对方,但是,因为雾霾等原因不能100%确认,所以,要通过招手的方式,相互确定对方是否认识自己。
我们看到这个过程中一共是四个动作,招手–点头微笑–招手–点头微笑。其中连续进行了2个动作,先是点头微笑(回复对方),然后再次招手(寻求确认),实际上,可以将这两个动作合一,招手的同时点头和微笑(syn+ack)。于是四个动作就简化成了三个动作,招手–点头微笑并招手–点头微笑。这就是三次握手的本质,中间的一次动作是两个动作的合并。
1.1.1.1 *TCP 数据传输:*
TCP 数据传输就是两个人隔空对话,差了一点距离,所以,需要对方反复确认听见了自己的话。
1.1.1.2 *tcp重传:*
客户端喊了一句话(data),接收方听见了,之后要回复自己听见了(ack)。
如果喊了一句,半天没听到对方回复,就认为自己的话被大风吹走了,没听见,所以,需要重新喊话,这就是tcp重传。
也有可能是服务端听到了客户端的话,但是Server向Client的回复被大风吹走了,以至于Client没听见Server的回复。Client并不能判断究竟是自己的话被大风吹走了,还是Server的回复被大风吹走了,Client也不用管,重传一下就是。
1.1.1.3 *A**ck确认:*
Client可以向Server喊话,同样Server也可以向Client喊话,因为tcp链接是「双工的」,双方都可以主动发起数据传输。不过无论是哪方喊话,都需要收到对方的确认才能认为对方收到了自己的喊话。
1.1.1.4 *批量ack:*
Client可能是个高射炮,一说连说了八句话,这时候Server可以不用一句一句回复,而是连续听了这八句话之后,一起向对方回复说前面你说的八句话我都听见了,这就是批量ack。
1.1.1.5 *TCP窗口大小:*
但是,Client也不能一次性说了太多话,Server的脑子短时间可能无法消化太多,两人之间需要有协商好的合适的发送和接受速率,这个就是「TCP窗口大小」。
1.1.1.6 *TCP三次连接总结:*
我们看到有两个中间状态,syn_sent和syn_rcvd,这两个状态叫着「半打开」状态,就是向对方招手了,但是还没来得及看到对方的点头微笑。
syn_sent是主动打开方的「半打开」状态,syn_rcvd是被动打开方的「半打开」状态。客户端是主动打开方,服务器是被动打开方。
1、 第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,即主动打开方的「半打开」状态,等待服务器B确认。
2、第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态,即被动打开方的「半打开」状态。
3、 第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。
1.1.1.7 *TCP 四次挥手:*
TCP断开链接的过程和建立链接的过程比较类似,只不过中间的两部并不总是会合成一步走,所以它分成了4个动作,Client挥手(fin)——Server伤感地微笑(ack)——Server挥手(fin)——Client伤感地微笑(ack)。
之所以中间的两个动作没有合并,是因为tcp存在「半关闭」状态,也就是单向关闭。Client已经挥了手,可是人还没有走,只是不再说话,但是耳朵还是可以继续听,Server呢继续喊话。等待Server累了,也不再说话了,超Client挥了挥手,Client伤感地微笑了一下,才彻底结束了。
上面有一个非常特殊的状态time_wait,它是主动关闭的一方在回复完对方的挥手后进入的一个长期状态,这个状态标准的持续时间是4分钟,4分钟后才会进入到closed状态,释放套接字资源。不过在具体实现上这个时间是可以调整的。
它就好比主动分手方要承担的责任,是你提出的要分手,你得付出代价。这个后果就是持续4分钟的time_wait状态,不能释放套接字资源(端口),就好比守寡期,这段时间内套接字资源(端口)不得回收利用。
它的作用是重传最后一个ack报文,确保对方可以收到。因为如果对方没有收到ack的话,会重传fin报文,处于time_wait状态的套接字会立即向对方重发ack报文。
同时在这段时间内,该链接在对话期间于网际路由上产生的残留报文(因为路径过于崎岖,数据报文走的时间太长,重传的报文都收到了,原始报文还在路上)传过来时,都会被立即丢弃掉。4分钟的时间足以使得这些残留报文彻底消逝。不然当新的端口被重复利用时,这些残留报文可能会干扰新的链接。
4分钟就是2个MSL,每个MSL是2分钟。MSL就是maximium segment lifetime——最长报文寿命。这个时间是由官方RFC协议规定的。至于为什么是2个MSL而不是1个MSL,我还没有看到一个非常满意的解释。
四次挥手也并不总是四次挥手,中间的两个动作有时候是可以合并一起进行的,这个时候就成了三次挥手,主动关闭方就会从fin_wait_1状态直接进入到time_wait状态,跳过了fin_wait_2状态。
1.1.1.8 *TCP四次分手总结:*
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后,就能发送一个FIN来终止这个方向的连接。收到一个 FIN,只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后,仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
1、客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。
2、服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
3、服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。
4、客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。