TCP状态转换图

TCP涉及连接建立和连接终止的操作可以用状态转换图来说明。

TCP为一个连接定义了11中状态,并且规定了如何基于当前状态以及该状态下接收的分节(TCP报文段)从一个状态转换为另一个状态。其状态转换图如下所示:

具体转化过程和转换条件如上图所示。

Comment and share

TCP的连接与建立

最常用的传输层协议包括TCP和UDP两种,当然除此之外还有其他协议。UDP是一种既不面向连接有不可靠的传输层协议,而TCP是一种面向连接的可靠的传输层协议,为了达到这个目的,其在设计上使用了差错检测,重传,累计确认,定时器以及用于序号和确认好的字段等等。

TCP的特点

TCP协议有以下特点:

  • 面向连接:TCP的连接不是一条电路的或者虚电路,其连接状完全保留在两个端系统中。
  • 可靠传输:TCP连接在传输消息的过程中保证了数据的可靠性,即保证数据在传输过程中不会丢失。
  • 点对点:一条TCP连接只能连接两个端点。
  • 全双工:如果一台主机上的进程A和另一台主机上的进程B建立了一条TCP连接,那么应用层数据就可以从A进程发送到B进程的同时,B进程也可以发送数据到A进程。

TCP报文段结构

TCP报文段是由首部字段和一个数据字段组成的,数据字段中包含应用程序需要发送的数据。通常报文段中通过MSS(max segment size)来限制报文段数据字段的最大长度。报文段的结构如下:

说明:

  • 源端口号与目的端口号指的是客户端和服务器端应用程序分别使用的端口号。用于识别主机上某一个特定的应用程序。
  • 序号(seq)为TCP报文段中数据其实字节的序号。
  • 确认号字段为(ACK)期待接收的下一个TCP报文段中数据的序号。
  • 首部长度:首部长度表示当前TCP报文的首部的长度,一般为20,即可以看到表中报文首部的长度为20个字节。但是有时选项中有一些内容,这个时候首部长度大于20。
  • 保留字:NULL
  • 标志位:当某一些标志位被设置的时候表达一些特定的含义。
    • UGR标识报文段中存在着紧急数据。其中紧急数据的指针字段存放在后面16位的紧急数据指针中。
    • ACK标识确认号字段生效,一般连接建立之后的内个报文段的ACK被会被设置
    • PSH:不常用
    • SYN:连接建立时的客户端发送的服务端的第一个报文段和服务端响应客户端的报文段中被设置,标识当前为建立连接的过程。
    • FIN:与SYN类似,它是在断开连接时被设置。
  • 互联网检验和:用于错误检测
  • 紧急数据指针:即为上述当UGR标志被设置时标识紧急数据的指针。
  • 选项:应用程序中自定义的首部的其他内容。
  • 数据:应用程序发送的真正数据。

TCP建立连接(三次握手)

TCP连接的过程可以简单描述为以下几个过程:

  • 第一次握手:客户端发送请求连接报文段到服务器。此报文段中SYN被设置为1,同时随机或者指定一个起始序号x。此时客户端进入SYN_SENT(同步已发送)状态。
  • 第二次握手:服务端收到请求报文段之后,向客户端发送确认报文段。确认报文段中ACK设置为1,SYN设置为1,确认号为x+1,同时为自己生成一个序号y。此时服务端进入SYN_RECV状态(同步接受到)。
  • 第三次握手:客户端收到服务端的确认报文段之后,还要给服务端发送一个确认报文段。这个报文段中ACK被设置为1,确认号为y+1。此报文段可以携带数据。

经过上述三个步骤之后,TCP连接建立成功。客户端进入连接建立状态(ESTABLISHED)。然后就可以相互发送数据了。

为什么要经过三次握手?

三次握手的目的是为了防止失效的报文段突然传送到服务端而出现问题。

上述已经失效的报文段是指:如果客户端在发送第一次连接请求的过程中,由于网络原因导致此报文段在某个网络节点滞留较长时间,这个时候TCP传输协议会视为此报文段已经丢失,于是重传。若此滞留的报文段在连接断开之后才到达服务器,这个时候就会出现问题。

若不是使用三次握手,服务器收到失效的报文段之后会建立连接,故之后无法释放TCP资源。导致资源浪费以致于长期会使服务器宕机。

三次握手过程中服务器和客户端程序的行为

  • 服务器必须准备好接受外来的连接,调用socket(),bind()以及listen三个函数来完成,我们称为被动打开。
  • 客户端通过调用connect发起主动打开连接,向服务器发送SYN(同步)包,connect函数阻塞。
  • 服务器通过accept接收到客户端来送的TCP包,需要进行确认同事发送自己的SYN包,此时accept函数阻塞,
  • 客户端收到服务器的SYN包,connect函数返回,并向服务器发送确认。服务器接收到确认之后accept函数返回。

TCP连接断开(四次挥手)

由于TCP连接是全双工的,因此每个方向都必须单独的关闭,也就是发送方和接收方都需要FIN和ACK。客户端和服务器都可以首先主动发送连接终止的报文。当其中一方发送完数据之后即可向另一方发出连接断开的请求。当收到FIN意味着这一方向上没有数据流动,但是一方收到FIN之后仍然可以发送数据。四次挥手的具体过程如下:

  1. 此时TCP连接两端都处于ESTABLISHED的状态,客户端停止发送数据,并发出一个FIN报文段。首部FIN设置为1,序号seq=u(u为客户端传输数据的字后一个字节的序号加1)。客户端进入FIN_WAIT-1状态。
  2. 服务端回复确认报文段,确认号为ack=u+1,序号为seq=v(v为服务端传输数据的最后一个字节序号加1),服务端进入close_wait状态。现在TCP连接处于半关闭状态,服务端如果继续发送数据,客户端依然接收。
  3. 客户端收到确认报文段,进入FIN_WAIT-2状态,服务端发送完数据之后,发出FIN报文段,FIN被置位1,确认号为ack=u+1,然后进入LAST_ACK状态。
  4. 客户端回复确认报文段。ACK=1,确认号为sck=w+1(w为半开半闭时收到的最后一个字节数据的编号),序号为seq=u+1,然后进入TIME_WAIT状态。

一段时间(大约4分钟)之后等待状态结束,连接两端进入CLOSED状态。

参考链接:

Comment and share

  • page 1 of 1

魏传柳(2824759538@qq.com)

author.bio


Tencent


ShenZhen,China