TCP的三次握手
TCP的连接的建立采用客户服务器方式。主动发起连接建立的应用进程称为客户端,被动的等待连接建立的应用进程叫做服务器。
先假定主机A运行的是客户端程序,而B运行的是服务器程序。最初两端的TCP进程都处于CLISED状态。建立三次握手过程如下图:
A主动打开连接,B被动打开连接
连接过程
1.首先两端都处于CLOSED状态,B的TCP服务器首先创建传输控制块TCB准备接受客户端的连接请求,然后服务器进程就处于LISTEN状态,等待客户的连接请求,如果有就及时做出反应。
2.A的TCP进程也是首先创建传输控制模块TCB,然后向B发送连接请求,同时初始化序号seq=x,并将SYN标志位置为1,此阶段为SYN报文段规定并不能携带数据,但也会消耗一个序号,此时TCP客户进程进入SYN-SENT(同步已发送)状态。
3.B如果接受连接请求就将确认报文中的ACK,SYN置为1,同时初始化自己的序号seq=y,确认号为ack=x+1.同样的这个报文也不能携带数据,并且也要消耗一个序号,然后B进入SYN-RCVD状态(同步收到)。
4.A收到B的确认后还需要再次向B给出确认,确认ACK置1,确认号ack=y+1,而自己的序号为seq=x+1,TCP规定ACK报文可以携带信息,但是如果不携带则不用消耗一个序号,这种情况下下次发送的序号仍然为seq=x+1。这时连接已经建立,A进入ESTAB-LISHED(已建立连接)状态。
当B收到A的确认后也进入ESTAB-LISHED状态。
至此三次握手到此结束
小思考,为什么要A还要给B发一次确认呢?或者说两次握手不就建立好了吗?
答:这样是为了防止已经失效的的连接请求再次传送到B,从而产生错误。
我们现在试着想一下这样一种正常的情况,A向B发送连接请求,但因为某种原因请求丢失了,A超时重传再次发送连接请求,传输完毕释放连接,A一共发送了两个请求,第一个丢失第二个正常收到,没有失效的连接请求报文段。但我们试想另一种极端的情况,那就是A第一次发送的请求并没有丢失而是因为网络延迟而滞留了,此时滞留的请求被B收到,B会以为这是A的新的一次请求,然后B进行确认应答然后进入连接状态(假设没有三次握手,两次握手就连接),可是B的确认传达到A,由于A并没有申请连接B,所以A不会理睬B的确认应答,也并不会给B发数据。可B一直在等A给他发消息,于是B的服务器资源被白白浪费。
而采用了三次握手,发生上述情况,由于A不会向B发送确认应当,B也就知道A没有连接的请求。
TCP的四次挥手
TCP的连接释放过程分为四个步骤,称为四次挥手,我们仍结合双方状态来探究释放的过程
1.在数据传输完成后双方都可以释放连接,现在双方都处于ESTAB-LISHED状态,现在由A首先先向其TCP发出释放连接报文段,并停止发送数据,主动关闭TCP连接。其通过将FIN位置1,seq=u(等于最后传送成功数据序号+1),同时A进入FIN-WAIT-1状态,等待B的确认。注意FIN报文段不携带数据也会占用一个序号。
2.B收到连接释放报文段后发出确认,ACK=1,ack=u+1,自身序号seq=x,同时B进入CLOSE-WAIT(关闭等待状态),这时TCP服务器通知上层进程,因此从A到B方向的连接就释放了,但由B到A还能发送信息。A收到B的确认应答进入FIN-WAIT-2状态等待B释放自己的报文段。这个状态可能持续一段时间。
3.若B没有数据要发送给A,B就会通知A断开连接,此时B的序号为最后发送的数据序号+1,seq=w,ack=u+1,并将FIN置为1,然后进入LAST-ACK(最后确认状态),并等待A的确认。
4.A收到B的连接释放报文段后必须对此发出确认,将ACK置为1,seq=u+1,ack=w+1.此时还并没有释放完毕,A会进入TIME-WAIT(时间等待状态),必须经过时间等待计时器设置的时间2MSL后A才进入CLOSED状态,可能对于现在的网络2分钟可能有点长,因此TCP允许不同实现的具体情况使用更小的MSL值,当时间等待结束,A回收x相应的传输控制块TCB后就结束了此次TCP连接,而B收到A的确认会立即进入CLOSED状态。
至此四次挥手结束!
小思考,为什么客户机A需要等待2MSL?
答:在这里有两个理由:
1.为了保证A发送的确认能够到达B,因为这个报文可能会丢失,而丢失了A可以重传确认并重新启动TIME-WAIT,如果A发送了确认不进行等待而立即释放,会导致B无法收到A的ACK确认从而无法完成B的释放。
2。为了防止前面提到的已失效连接请求报文段。A在发送完成最后一个ACK报文段后,在经历2MSL后,可以使所有本连接连续产生的所有报文段从网络中消失,这样使得下一次的新连接中不会出现这种就的请求报文。
保活计时器
上面介绍了TCP的正常断开步骤,可日常情况下可能有一些特殊的情况,比如意外的断电使得客户断不能告诉服务端自己断开链接了,此时应当有措施使得服务器不必白白等下去,因此设计了保活计时器,当服务端每次收到客户端数据都会重置保活计时器。,时间的设置通常是两个小时,如果两个小时都没有收到客户的数据,服务器就会发送一个探测报文,以后会间隔75分钟发一次,若连续10次仍然没有客户端的消息,服务器就认为客户端故障,接着关闭这个连接。