一:三次握手
我们在互联网上进行数据传输时,存在很大的风险,因为互联网不像单个网络,接受数据的一端和发送数据的一段可能存在很大的差异他们的带宽,拓扑,分组等等都有可能不一样;所以在互联网上传输信息是不安全的;为此产生了传输层控制协议TCP;
传输层控制协议(TCP)是一种面向连接的,可靠的提供字节流的协议;每一次进行数据传输时都会进行三个阶段:建立连接,传输数据,断开连接;
所谓的建立连接就是发起一次TCP连接请求:
A:客户端向服务端发送一个同步信号SYN(j=1)的数据包之后进入SYN_SEND状态
B:服务端在接受到客户端发送的SYN数据包之后,进入到SYN_RCVD状态;也要向客户端发送同步信号SYN和ACK(确认号)数据包表示自己收到了;
C:客户端接收到服务端发送的SYN和ACK(确认号)之后便进入到了Established状态;同时向服务端发送一个ACK(确认号)确认链接信息;服务端接收此信息之后进入到Established状态
那么问题来了?
为什么建立连接需要三次握手呢?
具体eg:客户端A向服务端B第一次发送请求时,由于服务端比忙没有理会A的请求,过了一段时间A又向服务端发起了第二次请求,此时第一次请求依然存在于网络上面的某一个地方;当第二次请求完成并且断开连接之后,第一次请求此时无意中又传递到了服务端B上,此时服务端以为客户端A又发起了一次连接呢。由于是两次请求;于是又向客户端发送数据报SYN和ACK之后便进入等待状态,但是其实客户端并没有再发起来连接请求了所以此时服务端白白浪费时间在哪里等待;但是如果我们采用三次请求就可以防止该种情况发生,当服务端B发送SYN和ACK数据报给客户端时,由于实际上客户端A并没有再次发送连接请求;此时客户端A收到报文之后一看就知道自己不应该理睬这个SYN报文段;此时客户端A就会想服务端B发送一个复位报文段即A拒绝了B的连接;B在收到A的复位报文消息之后,知道客户端不想见连接,便不会再进行等待了;
为了防止已经失效的连接请求报文段突然有传递到服务端,从而产生错误;
为了满足“在不可靠的信道上安全的传递信息”;
记住建立连接的三次握手不是有TCP协议决定的;信道不可靠数据的传输要可靠,最少三次请求才能满足;
二:四次挥手:
在客户端和服务端建立好了请求之后,便要开始传送数据了;当数据传送完之后他们就要将这个连接断开了;那么客户端具体是怎么样断开这个链接呢?这就涉及到我们常常讲的四次挥手了:
1:想要断开连接的一方(客户端)先向服务端发送一个FIN报文段,提示服务端我要断开连接了;之后便进入了FIN_WAIT1状态;这个状态不常见;
2:服务端在收到客户端发送的FIN报文消息之后会立刻个客户端发送一个确认信号ACK之后便进入ClOSE_WAIT状态;
(此时服务端关闭了读通道此时不能再从这条链接上从B读取数据)
此时客户端在接受服务端发送的ACK报文段之后便进入了FIN_WAIT2状态;同时客户端关闭自己的写通道,从现在可是不能从这条链接上向A写数据;
关于FIN_WAIT2状态其实是一种半连接状态,表示有一方想关闭连接但是另外一方还有数据要传输给你;此时被动关闭连接的一方依然可以向主动关闭连接的一方传递数据;
3:服务端发送完ACK之后,紧接着就会在此向客户端发送一个FIN报文段;便进入了LAST_ACK阶段;
4:客户端在接受到服务端发送的FIN报文段周便进入了TIME_WAIT状态;这个状态在window下面一般会持续4分钟左右;继续向服务端发送一个ACK的确认码之后便进入了Closed状态;服务端接受到ACK报文段之后便进入到了Closed状态;此时服务端关闭自己的写通道;
【问题1】为什么主动发起关闭连接的一方要进入TIME_WAIT转台而不是直接进入Closed状态呢?
一、保证TCP协议的全双工连接能够可靠关闭
二、保证这次连接的重复数据段从网络中消失
【问题2】为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
【问题3】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。