TCP传输控制协议(2)--TCP连接和终止

TCP的连接和终止

TCP的连接过程称为三次握手,其过程为,主动开启方(一般为客户端)发送SYN报文段指明想要连接的IP数据报端口,和自己的起始序列号,同时还会发送一个或多个选项,其中有MSS表示能接受的最大报文段(TCP数据段大小不包括首部)。
对方端(一般为服务器)接收到SYN请求后被动开启,回复一个SYN 报文段同时将发送自己的初始序列号,另外会将ACK 位置1,同时确认序号为对方序列号+1的值,同时也会发送一个或多个选项, 包括自己的MSS
客户端收到服务器的SYN + ACK报文段时会发送一个纯ACK包回复,其确认序号为对方SYN的序列号+1,纯ACK不占序号。
TCP关闭时首先需要关闭的一方发送一个FIN报文段,同时该报文段也可以将ACK置为1用于确认应答上一个数据包,被动关闭方在接受到FIN报文段时会回复一个ACK其确认序号为FIN报文段序列号加1,同时被动关闭方可以继续发送数据,因为TCP连接是一个双工通信,当被动关闭方发送完数据后,其同样向对方发送FIN报文段, 对方回复ack此时连接断开。

TCP状态转变

TCP连接过程中状态变换如图所示:
TCP传输控制协议(2)--TCP连接和终止_第1张图片

首先客户端和服务器均为close装态,服务器启动定义监听套接字,绑定端口和地址,同时执行listen函数进入listen状态等待连接到来,此时服务器accept会进入阻塞,客户端定义套接字,通过connect函数向服务器发起连接,客户端主动打开发送SYN请求,进入SYN_SENT状态等待服务端回复,当服务端收到SYN请求时回复SYN+ ACK进入SYN_RCVD状态,客户端收到该回复,发送ACK回复进入ESTABLISHED状态,服务器收到ack回复时同样进入ESTABLISHED状态,同时会分配新的描述符用于和客户端通信,而监听套接字会继续进行监听其他连接,此时服务器用accept返回的套接字和客户端进行通信,当执行close时则开始关闭该连接,如果此时发送缓存区中还有数据则发送这些数据,同时在发送最后一个报文段时将其FIN位置1,如果没有数据则直接发送FIN报文段,另外会丢弃接受缓存区的所有数据,此时进入FIN_WAIT_1状态等待对方回复,对方接受大FIN包后回复ACK进入CLOSE_WAIT状态,客户端收到ACK进入FIN_WAIT_2状态,如果此时数据发送完成调用close,会同客户端一样对缓存区进行处理同时发送FIN报文段进入LAST_ACK状态,客户端收到该FIN进入TIME_WAIT状态(后面说明)然后回复ack在两个MSL计时器后关闭,服务器收到该ACK 也会关闭该描述符。

TIME_WAIT状态

进入TIME_WAIT状态需要等连个MSL时间,MSL为报文最大生存时间,在IP首部有TTL字段,当TCP执行一个主动关闭并发送最终的ACK.时,连接必须处于TIME_WAIT状态并持续两倍于最大生存期的时间。这样就能够让TCP重新发送最终的ACK以避免出现丢失的情况。重新发送最终的ACK并不是因为TCP重传了ACK. (它们并不消耗序列号,也不会被TCP重传),而是因为通信另一方重传了它的FIN (它消耗一个序列号)。

重置报文段

在TCP头部中设置RST字段该报文被称为重置报文段,重置报文段一半会导致TCP连接的快速拆卸,一般有以下几种情况会收到RST报文,

  1. 当请求一个没有监听的端口时就会产生RST报文(UDP会发送端口不可达的ICMP消息)同时该RST必须将ACK置位并且确认序号必须为SYN序列号加1,这个是为了防止恶意RST影响连接,
  2. 应用程序主动通过RST消息终止一个连接,此时发送缓存区消息均会被丢弃,接收端接收到RST后也可以知道是对端主动终止了这个tcp连接
  3. 应用层还没有读取完接收缓存中的数据,连接被提前关闭
  4. TCP在TIME-WAIT状态下的时候,如果接收到RST报文,可能会提前结束TIME-WAIT状态,可以设置该状态是否受 RST影响
  5. 在半打开状态下发送数据,一般是如果连接没有建立成功就会处于半打开状态,如三次握手最后一个ack丢失,客户端认为连接建立成功发送数据时对方就会发送RST报文。

为什么连接时三次握手

这是一个面试中很常问的问题,TCP建立连接为什么是3次而不是4次或者其他次数,可以看建立连接的过程,在TCP建立时前两次均会发送SYN而SYN会消耗一个序列号,故TCP可以保证其可靠传输,如过SYN丢失,TCP会重新发送,该报文直到发送成功(收到确认ACK另外SYN丢失采用指数退避的方式发送,每次重新发送SYN后等待重发时间会加倍)最后一次握手发送纯ACK无序号如果该报文发送失败则TCP会认为,其SYN包未发送成功会进行重新发送SYN报文,此时会认为该方向上连接不成功。只有完成三次握手通信双方均会收到一次确认此时双方才会认为各自方向连接建立成功,如果次数再多的会冗余,少的话不够两次确认。

你可能感兴趣的:(Linux网络编程)