主要介绍TCP段头和TCP连接的建立与释放:

一、简介

TCP协议即传输控制协议(Transmission Control Protocol),是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。

二、TCP段的头

TCP每个段的起始部分是一个固定格式的20字节头,固定的头部之后可能有头的选项。如果该数据段有数据部分的话,那么在选项之后是最多可达65535-20(IP头)-20(TCP头)=65495个字节的数据。没有任何数据的TCP段也是合法的,通常被用作确认和控制消息。

  • 源端口和目的端口

标识了连接的本地端口。TCP端口加上所在主机的IP地址组成了48位的唯一端点。源端点和目标端点一起标识了一条连接。

  • 序号

TCP连接中传送的数据流中的每个字节都有一个编号,序号字段的值是指本报文段所发送数据的第一个字节的编号。

  • 确认号

期望收到的下一个报文段数据的第一个字节的序号。

  • TCP头长度

指明了TCP头包含多少个32位的字。这个信息是必需的,因为选项(options)字段是可变长的。

接下来是4位没有用到的字段和8个1比特的标志位:
  • CWR和ECE

用作拥塞控制信号,当TCP接收端收到了来自网络的拥塞指示后,就设置ECE以便给TCP发送端发送ECN-Echo信号,告诉发送端放慢发送速率。

TCP发送端设置CWR,给TCP接收端发CWR信号,接收端就知道发送端已经放慢速率,不必再给发送端发ECN-Echo信号。

  • URG

当URG为1时,紧急指针字段有效,表示此报文段中有紧急数据,应尽快传送。紧急指针指向从当前序号开始找到紧急数据的字节偏移量。

  • ACK

ACK为1时表示确认号字段有效,为0时表示该段不包含确认信息。

  • PSH

表示请求端一旦收到数据后立即将数据递交给应用程序,而不是将它缓冲起来直到整个缓冲区满为止。

  • RST

表示连接中出现问题(例如:主机崩溃或其他原因),必须释放连接,然后再重新建立。

  • SYN

用于连接建立的过程。在连接请求中,SYN=1和ACK=0表示该段没有捎带确认字段。在连接应答中,SYN=1、ACK=1,表示捎带了一个确认字段。

本质上,SYN位被用来同时表示CONNECTION REQUESTCONNECTION ACCEPTED,然后用ACK位来区分这两种情况。

  • FIN

用来释放连接,FIN=1表示发送端已经没有数据需要传输了,要求释放连接。

  • 窗口大小

TCP中的流量控制是通过一个可变大小的滑动窗口来处理的,此字段指定了从被确认的字节算起可以发送多少个字节。

  • 校验和

提供了额外的可靠性,它校验的范围包括头、数据以及与UDP一样的概念性伪头。

  • 选项

    提供了一种添加额外信息的途径,常用的有:可接收的最大段长(MSS)、窗口尺度、时间戳和选择确认选项。

    • MSS(Maximum Segment Size)

    允许每台主机指定它愿意接受的最大段长。

    • 窗口尺度(Window scale)

    允许发送端和接收端在连接建立阶段协商窗口尺度因子。

    • 时间戳(Timestamp)

    携带由发送端发出的时间戳,并被接收端回应。

    • 选择确认(SACK, Selective ACKnowledgement)

    使接收端可以告诉发送端已经接收到段的序号范围,是对确认号的补充。

三、连接建立

TCP使用了三次握手法来建立连接。为了建立一个连接,服务器先依次执行LISTEN和ACCEPT原语,然后被动地等待入境连接请求。客户端执行CONNECT原语,同时说明它希望连接到的IP地址和端口、它愿意接受的最大TCP段长以及一些可选的用户数据等参数。CONNECT原语发送一个SYN标志位为1和ACK标志位为0的TCP段,然后等待服务器响应。当这个TCP段到达接收方(服务器)时,接收方的TCP实体(库过程、用户进程或内核的一部分)检查是否有一个进程已经在目标端口字段指定的端口上执行了LISTEN。如果没有,则发送一个设置了RST的应答报文,拒绝客户端的连接请求。如果有,则将入境的TCP段交给该进程处理。该进程可以接受或拒绝这个连接请求。如果接受请求,则发送回一个确认段。

  1. 主机A的TCP向主机B发送连接请求的报文段,其首部中的同步位SYN=1,并选择序号seq=x,表示传送数据时的第一个数据字节的序号是x。

  2. 主机B的TCP接收到连接请求报文段后,如果同意,则发回确认段。在确认段首部中SYN=1、ACK=1,确认号为ack=x+1,并选择自己的序号为seq=y。

  3. 主机A的TCP收到主机B的确认段后再向主机B发出确认,其中ACK=1,确认号为ack=y+1;并通知其上层的应用进程,连接已经建立。

  4. 主机B的TCP收到主机A的确认后,也通知其上层的应用进程,连接已经建立。

四、连接释放

TCP连接是全双工的,为了释放一个连接,任何一方都可以发送一个设置了FIN标志位的TCP段,这表示它已经没有数据要发送了。当FIN段被另一方确认后,这个方向上的连接就被关闭了,不再发送任何数据。但另一个方向仍可能还在继续传输数据流。只有当两个方向都关闭后,连接才算被彻底释放。

通常情况下,释放一个连接需要4个TCP段:每个方向上一个FIN和一个ACK。第一个ACK可能和第二个FIN被组合到同一个段中,从而将所需段的总数降低到3个。

  1. 主机A发送释放连接的报文段,其首部FIN=1,选择序号seq=u,等待主机B的确认。

  2. 主机B发送确认报文段,其首部中确认号为ack=u+1,选择自己的序号为seq=v。

  3. 从主机A到主机B方向的连接被释放了,但TCP连接仍处于半关闭状态,主机B仍可向主机A发送数据。

  4. 主机B已经没有要向A发送的数据了,此时向主机A发送释放连接的报文段,其首部FIN=1,选择序号seq=w,等待主机A的确认。

  5. 主机A收到释放连接的报文后发送确认报文段,其中ACK=1,确认号为ack=w+1,选择自己的序号seq=u+1。

注意:

TCP连接必须经过2MSL(报文最大生存时间,Maximum Segment Lifetime)后才真正释放掉,原因:

  • 为了保证主机A发送的最后一个ACK报文段能够到达主机B

  • 防止”已失效的连接请求报文段”出现在本连接中。主机A在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续时间内产生的所有报文段都从网络中消失,这样就可以使得在下一个新的连接中不会出现旧的连接请求报文段。

参考资料: