简述TCP连接与释放过程中的三次握手和四次挥手及常见问题

TCP报文段的首部格式
简述TCP连接与释放过程中的三次握手和四次挥手及常见问题

URG:当URG=1时,表明紧急指针字段有效,告诉系统这个报文段里有紧急数据,优先传送。
ACK:当ACK=1时,确认号字段有效,ACK=0时确认号字段无效
PSH:收到TCP的PSH=1的报文段,就尽快的交付接受应用进程,而不用等到整个缓存都满了再向上交付。
RSH:当RSH=1时表明TCP连接出现错误,必须释放连接,然后再重新建立连接。
SYN:SYN=1时表示这是一个连接请求或连接接受报文。
FIN:FIN=1表示此报文段的发送端的数据以发送完成,并要求释放运输连接。


TCP连接的建立——三次握手

简述TCP连接与释放过程中的三次握手和四次挥手及常见问题

最开始客户端和服务器都是处于CLOAED状态的,其中客户端是主动打开连接,服务端被动打开连接。
第一次握手
客户端A的TCP向服务端B发送连接请求报文段,SYN=1请求连接,seq=x表示传送数据时第一个数据字节是x。此时TCP客户端进程进入SYN-SENT状态。
第二次握手
TCP服务端收到连接报文后如果同意连接则回复确认,其中SYN=1,ACK=1,确认号ack=x+1,自己的序号seq=y;此时TCP服务端进程进入SYN-RCVD状态。
第三次握手
客户端A收到确认报文后向服务端B给出确认,ACK=1,确认号ack=y+1,客户端通知上层应用进程建立已连接。此时TCP的客户端进程进入ESTAB-LISHED状态。当服务端B收到后就也进入ESTAB-LISHED状态,双方可以开始数据传送。

TCP连接的释放——四次挥手
简述TCP连接与释放过程中的三次握手和四次挥手及常见问题
第一次挥手
数据传输结束后双方都可以发出释放连接,假设客户端先释放连接。客户端向服务端发送连接释放报文并且停止发送数据,释放数据报文首部,FIN=1,***seq=u。此时客户端进入FIN-WAIT-1状态。等待B的确认。
第二次挥手
服务端收到连接释放报文后发出确认,确认号ack=u+1,报文段自己的序号seq=v,此时服务端进程进入CLOSE-WATE状态。这个时候客户端不再向服务端发送数据但是服务端如果还要继续向客户端发送数据,客户端照常接收,也就是终止等待的时间。客户端收到确认后进入FIN-WAIT-2状态。
第三次挥手
若服务端没有数据向客户端传送时其应用进程就会通知TCP释放连接,向客户端发送连接释放报文,发送FIN=1,ack=u+1,***seq=w,此时服务器进入LAST-ACK状态。。等待客户端的最后确认。
第四次挥手
客户端收到服务端连接释放报文后进入TIME-WAIT状态。,然后给服务端回一个最后的确认报文,这是TCP连接并没有被释放,而是等2MSL(报文段最长存活时间,超过这个时间报文将被丢弃)后才会被释放。服务端一旦收到确认,立马进入CLOSED状态,2MSL后客户端也进入CLOSED状态,本次TCP连接彻底结束。

常见问题
1.从图中就可以轻易的看出,当客户端A已经处于ESTAB-LISHED状态时,服端B还可能处于SYN-RCVD状态。其他情况同理。

2.为什么是三次握手
(1)防止已经失效的连接建立请求突然又传送到服务端了,导致错误。

假设A第一个给B发送建立连接请求,因为传送过程中在某个网络节点停留了很久,由于A迟迟没有收到B的确认报文,误以为请求丢失,于是重新向B发送请求。当A和B完成数据传送准备关闭连接时先前停留的请求报文到达了B,此时B会再次建立连接导致资源浪费。有第三次握手的情况下即使第一次迟到的报文不幸被B接受到了,A也不会发送确认报文,连接不会打开。

(2)假设第二次握手之后没有第三次握手,则服务端会在发送确认报文(第二次握手)后,开始发送数据,如果确认报文在客户端接收之前丢失,客户端没有收到,便不知道服务端建立了什么样的***,则客户端不会处理服务端发送过来的数据一直等待确认报文,而服务端发送的数据超时后会继续重传相同的数据造成死锁。

3.为什么等待2MSL
为了保证客户端发送的最后一个ACK报文段能到达服务端,如果没收到的话服务端会在超时后将重发第三次握手的FIN包,并且初始化计时器2MSL。还有就是防止之前失效的连接分组再次出现,而2MSL的时间足够让他消失。
4.为什么握手三次,挥手四次
建立连接时,ACK和SYN可以放在一个报文里来发送,其中ACK报文是用来应答的,SYN报文是用来同步的。而关闭连接时,被动关闭方可能还需要发送一些数据后,所以会先回复一个ACK确认报文,等服务端所有报文都发送完了再发送FIN报文表示同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
5.当建立连接后客户端出现故障怎么办
TCP设有一个保活计时器,客户端如果出现故障,服务器不会一直等下去造成资源浪费。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,然后关闭连接。