RFC793中文版

转自:https://blog.csdn.net/dlmu2001/article/details/1184366

传输控制协议(TRANSMISSION CONTROL PROTOCOL)
DARPA 互联网程序
协议规范

1981年9月

目录

    • 1.简介
      • 1.1 动机(Motivation)
      • 1.2 范围(Scope)
      • 1.3 关于这个文档
      • 1.4 接口
      • 1.5 操作
    • 2.体系(PHILOSOPHY)
      • 2.1 Internetwork系统的元素
      • 2.2 操作模型
      • 2.3 主机环境
      • 2.4 接口
      • 2.5 同其它协议的关系
      • 2.6 可靠通信(Reliable Communication)
      • 2.7 连接建立和清除(Connection Establishment and Clearing)
      • 2.8 数据通信(Data Communication)
      • 2.9 优先级和安全性
      • 2.10 坚固性原则(Robustness Principle)
    • 3. 功能性规范(FUNCTIONAL SPECIFICATION)
      • 3.1 头部格式
      • 3.2 术语(Terminology)
      • 3.3 系列号(Sequence Numbers)
      • 3.4 建立一个连接
      • 3.5 关闭一个连接
      • 3.6 优先级和安全性
      • 3.7 数据通信
      • 3.8 接口(Interfaces)
      • 3.9 事件处理(Event Processing)

1.简介

传输控制协议(TCP)在交换计算机通讯网络和这些网络的互联系统中作为一个高可靠性的主机到主机协议使用。

本文档描述了传输控制协议执行的功能,实现的程序,和程序接口或者要求它的服务的用户。

1.1 动机(Motivation)

计算机通信系统在军事、政府和民用环境中起着越来越重要的作用。本文档主要将注意力集中在军用计算机通讯要求,尤其是在不可靠通信中的坚固和在拥塞情况下的可用,但是很多这样的问题在民用和政府用途环境中也会碰到。

随着战略上和战术上的计算机通讯网络的发展和应用,提供一种方法来连接这些网络,以及提供可用的支持大量应用程序的标准进程间通信协议是必要的。预料到该标准的需要,国防研究和工程副部长宣告了这里描述的TCP协议,来作为DoD范围的互联协议标准的基础。

TCP是一个基于连接的、端到端的可靠协议,该协议设计以用来适应一个支持多个网络应用程序的层间协议结构。TCP提供了在属于不同的但是是互联的计算机通信网络的宿主主机中的进程对间的可靠进程间通讯。在TCP层之下,很少考虑到通信协议的可靠性。TCP假定它可以从底层协议获得一个简单的、潜在的不可靠数据报。原理上,TCP必须能够在一个从有线连接到包交换或者回路交换网络的比较大范围的通讯系统上工作。TCP基于Cerf和Kahn在[1]中第一次描述的概念。TCP适用于一个层间协议架构,该架构在一个基本的Internet协议之上,Internet协议为TCP提供了一种发送和接收封装在internet数据报中的可变长度分片的方法。internet数据报提供了在不同网络中寻址源和目的TCPs的方法。Internet协议也处理为在多个网络和互联网关上取得传输和投递所进行的TCP分片的分片和重组。internet协议也携带优先级、安全分类和TCP分片的分隔,因此这些信息可用通过多个网络进行端到端传输。

本文档大部分是在宿主计算机中位于高层协议下的TCP实现上下文中写的。有些计算机网络会通过承载有TCP和ip层以及网络特定软件前端计算机连接到网络。TCP规范描述了到高层协议的接口,这些接口即使对于前端情况也是
可实现的,同时一个适合的主机到前台(host-to-front)端协议也被实现。

                          Protocol Layering
                        +---------------------+
                        |     higher-level    |
                        +---------------------+
                        |        TCP          |
                        +---------------------+
                        |  internet protocol  |
                        +---------------------+
                        |communication network|
                        +---------------------+

                                Figure 1

1.2 范围(Scope)

TCP用来在多网络环境下提供一个可靠的进程到进程通讯服务。TCP用来作为在多网络条件下的通用的主机到主机协议。

1.3 关于这个文档

本文档提出了任何TCP实现所要求的行为的规范,包括同高层协议的交互以及同其它TCPs的交互。文档的其它部分提高了一个协议接口和操作的简要视图。第二部分概要描述了TCP设计的理论基础,第三部分提供了不同事件发生情况下(新分片到达,用户调用,错误等)的TCP要求的行为和TCP分片的详细描述。

1.4 接口

TCP接口一端是用户或者应用程序,另一端是底层协议如IP协议。

应用程序和TCP间的接口将详细阐述。该接口包含一套调用,类似于操作系统提供给应用程序操作文件的接口。比如,有打开和关闭连接以及在已经建立的连接上发送数据报的接口。同时希望TCP可以异步地同几个应用程序通信。虽然TCP的实现者有一定的自由设计适合于特定操作系统环境的接口,对任何一个合法的实现来说,都需要实现一个TCP/用户接口的最小接口集合。

除了认为存在一个机制可以互相异步地传递信息,TCP和底层协议的接口没有特别指定。通常希望底层协议来指定该接口。TCP设计来在一个非常通用的互联网络上工作。

本文档假定的底层协议是Internet协议[2]。

1.5 操作

如上所述,TCP的一个主要目的是在进程间提供可靠的,安全的逻辑回路或者连接服务。

为了在一个比较不可靠的相互通信上提供这个服务,系统要求提供如下功能:

  • 基本的数据传输(Basic Data Transfer)
  • 可靠性(Reliability)
  • 流控(Flow Control)
  • 多路(Multiplexing)
  • 连接(Connections)
  • 优先级和安全性(Precedence and Security)

TCP在这些领域的基本操作在下面的段落中描述。

基本数据传输:
TCP通过将一定量的字节打包成在internet系统上传输的分片,能够在用户之间在两个方向上传输连续的字节流。通常情况下,TCPs决定什么时候阻塞以及前推数据。

有时候用户需要确保他们所提交给TCP的所有数据都被传输。基于这个目的,定义了push功能。为了确认提交给TCP的数据报确实被传送了,发送用户指示数据必须被推给接收用户。Push导致了TCPs立即前推和投递数据给接收者。确切的push点对接收用户可能不可见,且push功能不提供一个记录边界标识。

可靠性(Reliability):
TCP必须从被internet通信系统破坏的,丢失的,复制的或者非正确顺序投递的数据中恢复。这是通过给每个传输的字节流分片一个系列号实现的,且要求从接收TCP有肯定的确认(ACK)。如果ACK在一个间隔内(timeout interval)没有收到,数据就重传。在接收端,系列号用来正确对分片排序(分片可能次序颠倒)以及排除重复分片。通过给每个传输分片增加一个校验和来处理损坏,在接收端进行检查,且丢弃损坏的分片。

流量控制(Flow Control):
TCP为接收者提供一个办法让其控制发送者发送的数据的数量。这是通过在每个ACK中返回一个窗口(“window”)来指示超过最后成功接收的一个分片的可接受的系列号码的范围。窗口指示了发送者在接收到进一步的允许前可以传输的字节的数量。

多路技术(Multiplexing):
为了允许在一个单独的主机里多个进程同时使用TCP通信机制,TCP提供了一套地址和端口。从internet通信层同网络和宿主地址连接,这形成了一个socket。一对socket标识了一个连接。也就是说,一个socket可能同时被使用在多个连接中。

绑定端口到进程被每个主机单独处理。但是,将常用的进程(如“logger”或者时间服务)隶属于众所皆知的socket被证明是有用的。这些服务就可以通过已知的地址获取到。建立和学习其它进程的端口地址可能包括更加动态的机制。

连接(Connections):
上面描述的可靠性和流量控制机制要求所有的TCPs为每个数据流发起和维护某些状态信息。这些信息的结合体,包括sockets,系列号,和窗口大小,被称为一个连接。每个连接被一套指定两端的sockets唯一指定。

当两个进程需要通信的时候,他们的TCPs必须首先建立一个连接(在每一端初始化状态信息)。当通信完成的时候,连接终止或者关闭以释放资源用于其它用途。

由于连接必须在不可靠的主机和不可靠的internet通信系统上建立,一个带有基于时钟的系列号的握手机制被用来避免连接的错误初始化。

优先级和安全(Precedence and Security):

TCP用户可以指示通信的安全性和优先级。当这些特性不需要的时候,规定采用缺省值。

2.体系(PHILOSOPHY)

2.1 Internetwork系统的元素

internetwork环境由连接到依次通过网关互联的网络的主机组成。这里的网络有可能是局域网络(比如 ETHERNET)或者大网络(比如ARPANET),但是任何一种情况都是基于包交换技术。产生和消费消息的活动代理是进程。在网络,网关和主机上不同层次的协议支持一个通信系统,该系统提供了进程端口之间在逻辑连接上的双向数据流。

术语包(packet)用在这里表示一个主机和它的网络之间的一次事务的数据。我们通常不用关心一个网络内交换的数据块的格式。

主机是附着在一个网络上的计算机,从通信网络的观点来看,是包的源和目的地。进程在主机里被视为活动的元素(根据相对普遍的定义,进程是在执行的程序)。终端和文件或者其它I/O设备都被视为通过进程的使用彼此通信的东东。因此,所有的通信被视为进程间通信。

既然一个进程可能需要在它自己和其它进程间区分通信流,我们想像每个进程可以有几个端口,通过这些端口,进程同其它进程的端口进行通信。

2.2 操作模型

进程通过调用TCP传输数据,调用时传递数据的缓冲。TCP将这些缓冲的数据打包成分片,然后调用internet模块来传输每个分片到目的TCP。接收TCP将一个分片中的数据放置到接收用户缓冲,然后通知接收用户。TCPs在分片里面包含了控制信息来确保可靠有序的数据传输。

Internet通信模型是由一个同每个TCP有联系的internet协议模块提供了到局域网络的接口,这个internet模块组装TCP分片到internet数据报,然后为这些数据报选路到一个目的internet模块或者中继网关。为了在局域网络上传输数据报,它被包含在一个局域网络桢中。

包交换可以执行进一步的包装,分片或者其它操作以投递局域网包到目的internet模块。

在一个网络间的网关上,从它的局域网包上来的internet数据报是未经包装的(unwrapped),这些数据报被检查以确定数据报下一个要经过的网络。然后Internet数据报被包装成适合于下一个网络的局域包,然后被选路到下一个网关或者最后的目的地。

允许网关将一个internet数据报分解成更小的internet数据报分片,如果这在下一个网络中传输是必要的话。要这样做,网关要产生一套internet数据报,每个携带一个分片。分片在接下去的网关中可能会进一步分解成更小的分片。Internet分片设计成目的internet模块可以组装分片成一个internet数据报的格式。

目的internet模块从数据报解开分片后(如果需要,经过重组数据报)传给目的TCP。

这个简单的操作被多个细节注释。一个重要的特性是服务类型。这给网关(或internet模块)提供了指导它选择在下一个网络上传输的服务参数的信息。包含在服务类型信息里面的是数据报的优先级信息。数据报也可以携带安全信息来允许主机和操作在不同安全级别环境上的网关来基于安全考虑正确隔离数据报。

2.3 主机环境

TCP被当作操作系统中的一个模块。用户就像他们访问文件系统那样访问TCP。TCP可以调用其它操作系统接口,比如,管理数据结构的接口。假设真正的对网络的接口由设备驱动模块控制。TCP不直接调用网络设备驱动,而是调用internet数据报协议模块,在internet数据报协议模块中调用设备驱动。

TCP机制并不排除在一个前端(台)处理器(front-end processor)上的TCP实现。但是,在这样一个实现中,一个主机到前台(host-to-front-end)的协议必须提供功能来支持在本文档中描述的TCP用户接口的类型。

2.4 接口

TCP/用户接口提供了用户可以调用的TCP的接口,这些接口用来打开或者关闭一个连接,发送或者接收数据,或者获取一个连接的状态信息。这些接口同操作系统中其它用户的接口相似,比如,打开,读取或者关闭一个文件的接口。

TCP/internet接口提供了在internet系统中发送和接收寻址到主机上的TCP模块的数据报。这些接口中可以传递地址(address),服务类型(type of service),优先级(precedence),安全(security)和其它控制信息。

2.5 同其它协议的关系

下图展示了TCP在协议层次结构中的地位:

       +------+ +-----+ +-----+       +-----+                    
       |Telnet| | FTP | |Voice|  ...  |     |  Application Level 
       +------+ +-----+ +-----+       +-----+                    
             |   |         |             |                       
            +-----+     +-----+       +-----+                    
            | TCP |     | RTP |  ...  |     |  Host Level        
            +-----+     +-----+       +-----+                    
               |           |             |                       
            +-------------------------------+                    
            |    Internet Protocol & ICMP   |  Gateway Level     
            +-------------------------------+                    
                           |                                     
              +---------------------------+                      
              |   Local Network Protocol  |    Network Level     
              +---------------------------+                      
  
                         Protocol Relationships
                               Figure 2.

TCP被期望能够有效支持高层协议。必须容易确定高层协议如ARPANET Telnet或者AUTODIN II THP和TCP的接口

2.6 可靠通信(Reliable Communication)

在一个TCP连接上的数据流可以可靠的顺序地投递到目的地。

传输通过系列号(sequence numbers)和确认(acknowledements)来确保可靠。概念上,每八位字节数据分配一个系列号码。一个分片里面的第一个八位字节数据同分片一块传输,被

称为分片系列号码。分片也携带一个确认号码,该确认号码是在相反方向的下一个期望的传输八位字节数据的系列号码。当TCP传输一个包含数据的分片的时候,他将该数据分片的拷贝放在重传队列中,然后开始一个定时器,当数据的确认收到的时候,该分片拷贝从队列中删除,如果在定时到达之前没有收到确认,分片被重传。

TCP的确认并不保证数据被投递到最后的用户,只是保证接收TCP将负起该责任。

为了控制TCPs之间的数据流量,采用了一个流量控制机制。接收TCP报告一个“窗口”(window)来发送TCP。这个窗口指定了接收TCP当前准备接收的数据的字节数目,该数据字节从确认号码开始。

2.7 连接建立和清除(Connection Establishment and Clearing)

为了鉴别TCP可能要处理的分散的数据流,TCP提供了一个端口标识。因为端口标识是每个TCP单独选择了,他们可能不是唯一的。为了在每个TCP内提供一个唯一地址,我们将标识TCP的一个internet地址和一个端口标识结合起来创建一个socket,这在所有互联的网络上是唯一的。

一个连接由两端的socket对完全指定。一个本地的socket可以参与到多个外部socket的多个连接。一个连接可以用来携带两个方向的数据,这就是“全双工”(full duplex)。

TCP可以自由地将端口和他们选择的进程联系起来。但是,在任何实现中,有些基本概念是必须的。必须有些众所皆知的sockets,在这些socket上TCP仅通过一些方法同合适的进程联系在一起。我们想像进程可以“拥有”端口,且这些进程仅可以在他们拥有的端口上发起连接。(实现拥有权的方式是一个本地问题,但我们想像一个请求端口用户命令,或者唯一分配一组端口给一个指定进程的方法,比如,将端口名字的高位同一个指定的进程联系在一起)

连接由带有本地端口和外部socket参数的OPEN调用被指定。反过来,TCP提供了一个(短的)本地连接名字,通过这个名字,用户可以在接下来的调用中索引到这个连接。这里有些关于一个连接的信息必须被记住。为了存储这些信息,我们假定有个称为传输控制块(Transmission Control Block :TCB)的数据结构。一个实现策略是将一个指向该连接的TCB的指针作为本地连接名字。OPEN调用也指定了连接的建立是主动要求的,还是被动接受的。

被动OPEN请求意味着进程要接受到来的连接请求而不是尝试初始化一个连接。通常请求一个被动OPEN的进程将接受任何调用者的连接请求。在这种情况下,全0的外部socket用来指示一个未指定的socket。未指定的外部socket仅在被动OPENs被允许。

一个服务进程如果希望为其它未知进程提供服务,要以未指定的外部socket发起一个被动的OPEN请求。然后连接可以通过请求连接到该本地socket的任何进程建立。如果这个本地socket已知用来同这个服务联系,这将是有帮助的。

将一个socket地址同标准服务联系起来的这种众所皆知的socket是一个便利的机制。比如,“Telenet-Server”进程永久地分配给一个特定的socket,其它的soket保留给文件传输(File Transfer),远程工作入口(Remote Job Entry),文本产生器(Text Generator),回声(Echoer)和Sink进程(后面三个进程测试用)。一个socket地址可能被保留来访问一个“Look-Up”服务,该服务将返回指定的socket,在该socket上一个新创建的服务将被提供。众所皆知的socket是TCP规范的一部分,但是分配socket给服务超出了这个规范。(参见[4])

进程可以创建(issue)被动OPENs,然后等待其它进程的匹配的主动OPENs,当连接建立时,TCP就会通知它。在同一时间彼此向对方发起主动OPENs的两个进程将被正确连接。这个弹性对支持分部式计算是至关重要的,在分部式计算中,各个部分异步行动,不考虑对方。

在本地被动OPENs和一个外部主动OPENs时有两种匹配socket的基本情况。第一种情况,本地被动OPENs完全指定了外部socket,在这种情况中,匹配是精确的。第二种情况,本地被动OPENs未指定外部socket,在这种情况下,任何外部的socket只要本地socket匹配就被接受。其它可能的情况包括部分严格匹配。

如果有几个具有相同本地socket的悬而未决的被动OPENs(记录在TCBs),如果存在一个指定了外部socket的TCB,则在选择一个未指定外部socket的TCB之前,外部主动OPEN将被匹配到该TCB。

建立连接的工程利用了同步控制标志(SYN),包含了三条消息的交换。这个交换被称为三步握手[3]。

通过包含一个SYN的到达分片和由用户OPEN命令创建的一个等待TCB条目的集合点,连接被发起。当一个连接被发起时,判定本地和外部socket的匹配。当系列号(sequence numbers)在两个方向被同步的时候,连接创建。

连接的清除也包括分片的交换,此时,携带的是FIN控制标志。

2.8 数据通信(Data Communication)

在一个连接上的数据流可以视为字节流。发送用户在每个SEND调用中指示数据是否要通过PUSH标志的设置被立即推给接收用户。

发送TCP允许集结从发送用户过来的数据,以他们便利的方式以分片发送那些数据,直到push函数被标记,然后它发送所有的未发送的数据。当接收TCP看到PUSH标志,它必须立即将数据传递给接收进程而不是等待发送TCP的其它数据。

Push功能和分片边界之间没有必然联系。在任何特定分片的数据可以是一个单独的SEND调用的结果,全部或者部分,或者是多个SEND调用。

PUSH功能和PUSH标志的目的是把数据从发送用户推给接收用户。它不提供一个记录服务(record service)。

Push功能和TCP/用户接口的数据的缓冲的使用有个结合点。每次,一个PUSH标志同放到接收用户缓冲的数据联系在一起,即使缓冲没有满也会返回给用户处理。如果数据到达,且在发现PUSH标志前充满了整个缓冲,数据以缓冲大小为单元传给用户。

TCP还定义了一种同数据接收者通信的方法,就是在某些点上,有紧急数据,接收者正在读取(TCP also provides a means to communicate to the receiver of data that at some point further along in the data stream than the receiver is currently reading there is urgent data.)。TCP并不尝试定义用户在收到悬而未决的紧急数据的通知时确定的行为,但是通用的观念是接收进程将很快采取行动处理紧急数据。

2.9 优先级和安全性

TCP使用internet协议的服务类型头部和安全选项来在每个连接上提供优先级和安全性。不是所有的TCP模块必须在多级别安全环境下起作用。有些可能仅限于未分类使用,其它可能仅在一个安全级别和隔离上操作。从而,有些TCP实现和对于用户的服务可以限制在多级别安全场合的一个子集上。

运行在多级别安全环境的TCP模块必须正确标记外出的分片的安全性,分隔和优先级。这样的TCP模块必须同时提供他们的用户或者高层协议入Telnet或者THP一个接口以允许他们指定要求的安全级别,分隔和连接优先级。

2.10 坚固性原则(Robustness Principle)

TCP实现遵循了一个通用的坚固性原则:对自己所做的保守,对从其它地方接受的自由。

3. 功能性规范(FUNCTIONAL SPECIFICATION)

3.1 头部格式

TCP分片作为internet数据报发送。Internet协议头部携带了一些信息头部,包括源主机地址和目的主机地址[2]。TCP头部也仿效Internet头部,提供TCP协议的一些特定信息。这种区分考虑了除了TCP外的主机级别协议的存在。

TCP头部格式

    0               1               2               3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |        Source Port             |        Destination Port      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                               Figure 3.
  • 源端口(Source Port):16 bits源端口号码

  • 目的端口(Destination Port):16 bits目的端口号码

  • 系列号(Sequence Number):32 bits
    本分片的第一个数据八位字节的系列号码(除当SYN出现时外)。如果出现SYN标志,系列号是初使系列号(initial sequece:ISN),且第一个数据八位字节是ISN+1.

  • 确认号码(Acknowledgment Number):32 bits
    如果设定了ACK控制位,则这个头部包含了分片接收者期待接收的下一个系列号码。一旦连接建立,这个头部就总是发送。

  • 数据偏移(Data Offset): 4 bits,TCP首部长度TCP头部中32bit双字(words)的数目。指示了数据从哪里开始。TCP头部(即使是包含选项的头部)是32bits长度的整数号码。

  • 保留(Reserved):6 bits
    保留以后使用。必须是0值。

  • 控制位(Control Bits):6 bits(从左到右):

    • URG:紧急指针字段有效(Urgent Pointer field significant)

    • ACK:确认头部字段有效(Acknowledgment field significant)

    • PSH:强制函数(Push Function)

    • RST:重置连接(Reset the connection)

    • SYN:同步系列号码(Synchronize sequence numbers)

    • FIN:再没有来自发送者的数据(No more data from sender)

  • 窗口(Window):16 bits
    接收端正准备接收的数据八位字节的数目,开始于确认字段(acknowledgment)指示的位置。

  • 校验和(Checksum):16 bits
    在头部和文本中的所有16 bit字的补偿总和。如果分片包含一个0值的头部和文本八位字节要检验,为校验用最后一个八位字节右边填充0值以构成一个16 bit的字。填充不作为分片的一部分传送。当计算校验和的时候,校验和字段自己被0代替。
    校验和也包括TCP头部之前的伪头部。这些伪头部包括源地址,目的地址,协议和TCP长度。这可以避免报文被错误地路由。这些信息在Internet协议中携带,在TCP/Network接口的参数中传递,或者是TCP调用IP的返回值。

                     +--------+--------+--------+--------+
                     |           Source Address          |
                     +--------+--------+--------+--------+
                     |         Destination Address       |
                     +--------+--------+--------+--------+
                     |  zero  |  PTCL  |    TCP Length   |
                     +--------+--------+--------+--------+

TCP长度是TCP头部加上数据长度的八位字节数(这不是一个明确传输的数量,但是被计算),且它不计入12个八位字节的伪头部。

  • 紧急指针(Urgent Pointer):16 bits

该字段传达了紧急指针的当前值,是该分片里面从系列号码开始的正偏移。紧急指针指向根据紧急数据后面的八位字节的系列号码。该头部只有当URG控制位设置时才有效。

  • 选项(Options):可变

选项位于TCP头部后面,长度上是8 bits的整数倍。所有选项包含在校验和中。选项可以开始于任何八位字节巴结。选项的格式有两种情况:

1:单独的选项类型(option-kind)的八位字节

2:选项类型的八位字节,选项长度的八位字节,以及真正的选项数据字节。

选项长度(option-length)计入了选项类型(option-kind),选项长度(option-length)以及选项数据(option-data)。

注意选项列表可能比数据偏移字段暗示的短。超过End-of-Option选项的头部的内容必须进行填充。

TCP必须实现所有的选项

当前定义的选项包括:

类型 长度 意义

0 ----- 选项列表的结束

1 ----- 无操作

2 4 最大分片大小

特定选项定义:

选项列表的结束(End of option list)

        +--------+
        |00000000|
        +--------+
         Kind=0

选项代码指示了选项列表的结束。这可能同根据数据偏移字段得到的TCP头部不一致。这个选项用在所有选项的结束,而不是每个选项的结束。且仅在选项的结束同TCP头部的结束不一致的情况下需要使用

无操作(No Operation):

        +--------+
        |00000001|
        +--------+
         Kind=1

该选项代码可以在选项之间使用,比如,为了在一个字边界上对齐接下来的选项的开始。不保证发送者使用这个选项,所以接收者必须准备处理没有在一个字边界对齐的选项。

最大分片大小(Maximum Segment Size)

        +--------+--------+---------+--------+
        |00000010|00000100|   max seg size   |
        +--------+--------+---------+--------+
         Kind=2   Length=4

最大分片大小选项数据(Maximum Segment Size Option Data):16 bits

如果这个选项存在,则其指示了发送这个分片的TCP的最大接收分片。这个字段必须仅在初始化连接请求阶段发送(比如,在SYN 控制位设置的分片)。如果不使用这个选项,则允许任意大小的分片。

填充(Padding):可变

3.2 术语(Terminology)

在深入探讨TCP的操作之前,我们需要详细介绍一些术语。TCP连接的维持要求记住一些变量。我们设想这些变量存储在一个连接记录中,称这个连接记录为传输控制块(Transmission Control Block :TCB)。在存储在TCB的变量中,有本地和远端socket编号(local and remote socket numbers),安全(security)和连接优先级(precedence of connection),用户发送和接收缓冲的指针,重传队列和当前分片的指针。另外还有一些同发送和接收系列号相关的变量存储在TCB中。

发送系列号变量

  • SND.UNA - 发送 未经确认(send unacknowledged)

  • SND.NXT - 发送下一个(send next)

  • SND.WND - 发送窗口(send window)

  • SND.UP - 发送紧急指针(send urgent pointer)

  • SND.WL1 - 供最后窗口更新的分片系列号(segment sequence number used for last window update)

  • SND.WL2 - 供最后窗口更新的分片确认号码(segment acknowledgment number used for last Window update)

  • ISS - 初始发送系列号(initial send sequence number)

接收系列号变量

  • RCV.NXT - 接收下一个(receive next)

  • RCV.WND - 接收窗口(receive window)

  • RCV.UP - 接收紧急指针(receive urgent pointer)

  • IRS - 初始接收系列号(initial receive sequence number)

下面的图可以帮助你将这些发送系列号空间的变量联系起来。

发送系列号空间

                   1         2          3          4     

              ----------|----------|----------|----------

                     SND.UNA    SND.NXT    SND.UNA       
                                         + SND.WND   

1 - 已经确认过的老的系列号

2 - 未确认过的数据的系列号

3 - 新数据传送的系列号(sequence numbers allowed for new data transmission)

4 - 当前不允许传送的将来的系列号

发送窗口是图中3所标注的空间

接收系列号空间:

                       1          2          3     

                   ----------|----------|----------

                          RCV.NXT    RCV.NXT       
                                   + RCV.WND       

1 - 已经确认的老系列号

2 - 新接收的系列号(sequence numbers allowed for new reception)

3 - 现在不允许的将来的系列号(future sequence numbers which are not yet allowed)

接收窗口是图中2所标注的空间

还有一些变量经常使用,它们是从当前分片的字段中取值的。

当前分片变量

  • SEG.SEQ - 分片系列号(segment sequence number)

  • SEG.ACK - 分片确认号码(segment acknowledge number)

  • SEG.LEN - 分片长度(segment length)

  • SEG.WND - 分片窗口(segment window)

  • SEG.UP - 分片紧急指针(segment urgent pointer)

  • SEG.PRC -分片优先级值(segment precedence value)

连接过程在生存时间内经过一系列的状态。LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT,和最后的虚构状态CLOSED。CLOSED是虚构的因为处于CLOSED状态的时候已经没有TCB,也就是说没有连接。下面是这些状态的简单意义:

  • LISTEN - 等待从任何远端TCP和端口的连接请求

  • SYN-SENT -发送完一个连接请求后等待一个匹配的连接请求

  • SYN-RECEIVED - 发送连接请求并且接收到匹配的连接请求以后等待连接请求确认

  • ESTABLISHED - 表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传
    输阶段的正常状态。

  • FIN-WAIT-1 - 等待远端TCP的连接终止请求,或者等待之前发送的连接终止请求的确认

  • FIN-WAIT-2 - 等待远端TCP的连接终止请求

  • CLOSE-WAIT - 等待本地用户的连接终止请求

  • CLOSING - 等待远端TCP的连接终止请求确认

  • LAST-ACK - 等待先前发送给远端TCP的连接终止请求的确认(包括它字节的连接终止请求的确认)

  • TIME-WAIT - 等待足够的时间过去以确保远端TCP接收到它的连接终止请求的确认

  • CLOSED - 不在连接状态

TCP连接响应不同的事件从一个状态过渡到另一个状态。事件是用户调用,OPEN,SEND,RECEIVE,CLOSE,ABORT,和STATUS;到来的分片,特别是那些包含SYN,ACK,RST和FIN标志的分片;超时。

下图仅展示了状态变化,及导致变化的事件和引起的行为,但是未连接的错误情况和行为不包含在内。在后面的章节,将提供更详细的描述。

注:该图仅是摘要,不能当作所有的规范。

                             +---------+ ---------/      active OPEN  
                              |  CLOSED |            /    -----------  
                              +---------+<---------/   /   create TCB  
                                |     ^              /   /  snd SYN    
                   passive OPEN |     |   CLOSE        /   /           
                   ------------ |     | ----------       /   /         
                    create TCB  |     | delete TCB         /   /       
                                V     |                      /   /     
                              +---------+            CLOSE    |    /   
                              |  LISTEN |          ---------- |     |  
                              +---------+          delete TCB |     |  
                   rcv SYN      |     |     SEND              |     |  
                  -----------   |     |    -------            |     V  
 +---------+      snd SYN,ACK  /       /   snd SYN          +---------+
 |         |<-----------------           ------------------>|         |
 |   SYN   |                    rcv SYN                     |   SYN   |
 |   RCVD  |<-----------------------------------------------|   SENT  |
 |         |                    snd ACK                     |         |
 |         |------------------           -------------------|         |
 +---------+   rcv ACK of SYN  /       /  rcv SYN,ACK       +---------+
   |           --------------   |     |   -----------                  
   |                  x         |     |     snd ACK                    
   |                            V     V                                
   |  CLOSE                   +---------+                              
   | -------                  |  ESTAB  |                              
   | snd FIN                  +---------+                              
   |                   CLOSE    |     |    rcv FIN                     
   V                  -------   |     |    -------                     
 +---------+          snd FIN  /       /   snd ACK          +---------+
 |  FIN    |<-----------------           ------------------>|  CLOSE  |
 | WAIT-1  |------------------                              |   WAIT  |
 +---------+          rcv FIN  /                            +---------+
   | rcv ACK of FIN   -------   |                            CLOSE  |  
   | --------------   snd ACK   |                           ------- |  
   V        x                   V                           snd FIN V  
 +---------+                  +---------+                   +---------+
 |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
 +---------+                  +---------+                   +---------+
   |                rcv ACK of FIN |                 rcv ACK of FIN |  
   |  rcv FIN       -------------- |    Timeout=2MSL -------------- |  
   |  -------              x       V    ------------        x       V  
    / snd ACK                 +---------+delete TCB         +---------+
     ------------------------>|TIME WAIT|------------------>| CLOSED  |
                              +---------+                   +---------+

                    TCP Connection State Diagram
                               Figure 6.

3.3 系列号(Sequence Numbers)

设计上的一个基本观点是在一个TCP连接上发送的每个八位字节的数据都有一个系列号码。因为每个八位字节是编过序号的,所以每个都可以被确认。所使用的确认机制是累积的,所以序号X的确认指示的是所有X之前但不包括X的数据已经收到了。这种机制在重传中允许用来作为直接的复制检测。在一个分片内的八位字节的编号机制是紧跟头部之后的第一个数据八位字节是最小编号的,接下来进行顺序编号。

需要记住的是实际的系列号码空间是有限的,但是是很大的。该空间从0到2**32-1。因为空间是有限的,所有的处理系列号的算法必须执行模2**32。当系列号从2**32-1循环到0的时候,算法保留系列号的关系。计算模算法有些微妙,必须在比较这些值的编程的时候谨慎考虑。符号“=<“表示”小于或者等于“(模2**32)。

TCP必须执行的典型的一种系列号比较包括:

(a)确定一个确认指向的是有些系列号码已经发送但是未经确认

(b)确定一个分片的所有系列号码被确认(比如,用以将分片从重传队列中移除)

(c) 确定到来的分片包含了期望的分片(比如,分片同接收窗口交迭)

作为发送数据的响应,TCP会收到确认(acknowledgements)。在处理确认的时候需要做如下比较:

  • SND.UNA = 最老的未确认的系列号

  • SND.NXT = 下一个要发送的系列号

  • SEG.ACK = 接收TCP发送过来的确认(接收TCP期望的下一个系列号)

  • SEG.SEQ = 分片的第一个系列号

  • SEG.LEN = 分片中数据占有的八位字节号码(包括SYN和FIN)

  • SEG.SEQ+SEG.LEN-1 = 分片的最后一个系列号

一个新的确认(称为“可接受的ack”),遵循下面的不等式:

  • SND.UNA

如果重传队列中的一个分片的系列号和长度的和小于或者等于到来分片中的确认的值,则该分片被完全确认。

收到数据的时候,需要进行下面的比较:

  • RCV.NXT = 在到来分片中期待的下一个系列号,且是接收窗口的左或下边缘

  • RCV.NXT+RCV.WND-1 = 到来分片中期待的最后一个分片,且是接收窗口的右或上边缘

  • SEG.SEQ = 到来分片占据的第一个系列号

  • SEG.SEQ+SEG.LEN-1 = 到来分片占据的最后一个系列号

一个分片被认为用来占据合法系列空间的一部分,如果:

  • RCV.NXT =

或者

  • RCV.NXT=

第一部测试是检查分片的开始部分是否在窗口内,第二部测试是检查分片的结尾是否在窗口内,如果分片通过了这两步测试,则它包含了窗口内的数据。

实际情况要比这复杂。由于零窗口和0长度分片的存在,到来分片的接收有4种情况:

    Segment Receive  Test

    Length  Window

    ------- -------  -------------------------------------------
       0       0     SEG.SEQ = RCV.NXT

       0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

      >0       0     not acceptable

      >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
                     or 
                     RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND

注意当接收窗口为0的时候,除了ACK分片外的其它分片都不被接受。因此,TCP在传输数据和接收ACKs时维护一个0接收窗口是可能的。但是,即使当接收窗口是0,TCP必须处理所有到来分片的RST和URG字段。

初始化系列号选择

我们也利用编号机制来保护某些控制信息。这是通过在系列号空间中明显地包含一些控制标志让这些分片可以无冲突地被传输和确认来实现的(比如,一个且只有一个控制的拷贝被遵循)。控制信息在物理上不在分片数据空间携带。因此,我们必须采用暗中分配系列号给控制信息的规则。SYN和FIN是要求这个保护的控制信息,且这些控制信息仅在连接打开和关闭的时候使用。为了系列号的用途,SYN被认为出现在它出现的分片的第一个真实数据字节之前,而FIN被认为出现在它出现的分片的最后一个字节之后。分片长度包含数据和控制信息占据的系列号空间。当SYN出现的时候,SEG.SEQ是SYN的系列号。

协议不限制一个特定的连接被一次又一次的使用。连接被定义成一对socket。一个连接的新实例将当成连接的化身。这就引起了问题“TCP如何从之前连接化身的分片区分出复制分片”。如果连接关闭后被快速地打开,或者当连接由于内存丢失而断开然后重建,这个问题就变得很明显。

为了避免混淆,必须防止连接的一个化身的分片当同样的系列号存在于更早的化身的网络上的情况下被使用。我们要确保这点,即使TCP崩溃,丢失了他使用过的系列号码的所有信息。当新的连接建立的时候,初始化系列码(intitial sequence number :ISN)产生器被调用,该产生器选择了新的32位的ISN。该系列码产生器一定要有(可能是虚构的)个32位时钟,时钟的低位是每4微妙增长。也就是说,ISN大概每4.55个小时循环一次。因此我们假定分片不会在网络上停留超过最大分片生命周期(Maximum Segment Lifetime:MSL),且MSL小于4.55个小时,这样,我们就有理由假定ISN是独一无二的。

每个连接有一个发送的系列号和一个接收系列号。初始的发送系列号(ISS:initial send sequence number)由发送数据的TCP选择,初始的接收系列号(IRS:initial receive sequence number)在连接建立阶段得到。

一个连接要建立或者初始化,两个TCPs必须在双方的初始化系列号上同步。这是通过携带称为SYN(同步用)的控制位和初始化系列号的连接建立分片的交换完成了。作为一个速记标识,携带SYN位的分片也称为”SYNs”。然后,解决方案需要一个适宜的机制选择初始系列号以及细微地参与交换ISN的握手过程。

同步需要每一端发送它自己的初始化系列号,且从另一端通过ACK接收确认。每一端也必须接收另一端的初始化系列号并且发送一个确认ACK

1) A-->B   SYN 我的系列号是X

2) A<--B   ACK 你的系列号是X

3) A<--B   SYN 我的系列号是Y

4) A-->B   ACK 你的系列号是Y

因为步骤2和3可以结合在一条消息里面,所以这个过程称为3次握手。

因为系列号不依赖于一个网络中的全局时钟,所以三次握手是需要的,TCPs可以有不同的机制来挑选ISN。第一个SYN的接收者无法知道分片是否是个旧的延迟的分片,除非它记得上次用于连接的系列号(这往往是不可能的),因此它必须要发送者验证这个SYN。三次握手以及时钟驱动机制的优点在[3]中会进行讨论。

知道什么时候保持静止

为保证TCP不会产生一个携带了保留在网络中的老的分片的系列号的分片,TCP如果是从一个崩溃中启动或者恢复必须在一个最大分片生命周期内保持静止,在这个周期内,在使用的系列号内存被丢弃,这个周期之后才可以分配任何系列号。本规范设定MSL为2分钟。这是个工程上的选择,如果经验指示它需要做出修改他就可以修改。注意如果TCP被在某种意义上重新初始化,却仍然保留在使用的系列号内存,那么它不需要等待,它仅需保证使用大于那些刚被使用过的系列号码。

TCP静止时间概念(The TCP Quiet Time Concept)

规范规定那些崩溃(crash)且未能保持任何在每个活动(而不是关闭的)连接传输的系列号的信息的主机必须延迟发送任何TCP分片,这个延迟至少是在主机作为一部分的internet系统上经过协议的最大分片生命周期(MSL)。在下面的段落中,将给出规范的解释。TCP实现者可以违反“静止时间”限制,但是有可能导致某些老数据被internet系统上的某些接收者当作新数据接收或者新数据被接收者当作老的复制分片拒绝的风险。

每次形成一个分片然后进入在源主机的网络输出队列,TCPs消耗了系列号空间。TCP协议的复制检测和系列号算法依赖于分片数据同系列号空间的唯一绑定关系,假定系列号在绑定于该系列号的分片被投递和确认且所有复制拷贝已经在internet上消失之前不会循环了所有了2**32的值。如果没有这个假设,两个不同的分片可能被分配了一个同样的或者重叠的系列号,导致接收者对哪个数据是新的哪个数据是老的产生混淆。每个分片会被分配一串连贯的系列号,跟他们分片中的八位字节数目一样。

正常情况下,TCP会记录下一个要发送的系列号和最老的等待确认的分片的系列号,这样子可以避免错误地使用一个它的第一次使用还未被确认的系列号。仅仅这样并不能保证老的重复数据已经在网络上消失,因此系列号空间需要足够大以减少闲置重复分片到来导致的麻烦的可能性。在2兆/秒情况下,需要4.5个小时才能用光2**32个八位字节的系列号空间。由于网络上的最大分片生命周期不太可能超过几十秒,因此这被认为对可以预见的网络的足够保护,即使数据传输率上升到10兆/秒。在100兆/秒的条件下,循环时间是5.4分钟,这看起来有点短,但仍然在合理范围内。

但是,如果一个源TCP不记得它前次在一个给定连接上使用的系列号的话,TCP中的基本的重复分片检测和系列号算法可能被击败。比如,如果TCP以系列号0开始所有的连接,那么在崩溃或者重启的时候,一个TCP可能重新形成了一个较早的连接(可能是在半打开连接解决方案(half-open connection resolution)之后),且发送了系列号等于或者覆盖在同一个连接的较早化身上的系列号码的包。在不知道使用于一个特定连接的系列号信息的情况下,TCP规范建议源主机在发送分片之前延迟MSL的时间,以让那么较早连接化身发出的分片有时间从系统上消失。

即使主机能够记住时间并且用它来确定初始系列号值,也不能确保没有这个问题(比如,即使时间用来确定每个新的连接化身的初始系列号值)。

比如,假设一个连接以系列号S打开。假定这个连接没有怎么使用,最后初始化系列号函数(ISN(t))采用了一个值S1,这个S1是TCP在一个特定的连接上发送的最后一个分片。现在假定在这个时候,主机崩溃,恢复,然后建立了该连接的一个新化身。初始系列号是S1=ISN(t),刚好是连接的老化身上使用的最后一个系列号!如果恢复足够快速,在产生系列号的网络上任何S1相邻的重复分片都可能到来且被连接的新化身接收者视为新的数据包。

处理这个问题的一种方法是在从崩溃中恢复后特意地延迟发送分片一个MSL的时间,这就是“静止时间”规范。那些想避免等待且乐于接受老数据包和新数据包可能在目的主机产生混淆的风险的主机可以选择不等待“静止时间”。实现者可以提供TCP用户选择在以连接为基础的连接是否在崩溃或等待一段时间的能力,或者可以非正式的对所有连接实现“静止时间”。显然,即使一个用户选择“等待”,主机也并不一定要等待MSL这么长的时间。

总结:每个发送的分片在系列号空间中占据了一个或者多个系列号,被一个分片占用的号码在过去MSL时间之前都是“忙”或者“在用”,崩溃的时候,一块系列号空间被最后发送的分片的八位字节占用,如果新的化身太快启动且使用了同一个连接的前一个化身的最后分片的系列号空间范围内的系列号,这些潜在的系列号空间覆盖可能导致接收者产生混淆。

3.4 建立一个连接

“三次握手”“是用来建立一个连接的程序。这个程序一般是由一个TCP发起,另一个TCP响应。如果两个TCP同时发起该程序,也可以工作。当同时尝试发起产生的时候,一个TCP在发送了一个“SYN”分片以后接收到一个没有携带确认的“SYN”分片。当然,一个老的重复的“SYN”分片的到达也可能使这种情况发生。正确的“reset”分片的使用可以消除这种情况下的歧义。

下面是一些连接发起的例子。虽然这些例子没有展示使用携带数据的分片的连接同步,这是完全合法的,只要接收TCP没有在清楚的知道数据是合法之前将数据投递给用户(比如,数据必须在接收者的缓冲上进行缓存直到连接到达ESTABLISHED状态)。三次握手降低了错误连接的可能性。这是实现者在内存和提供检查信息的消息之间的一个平衡。

最简单的三次握手入下图所示。图中,每条线为引用方便被编号。右箭头(–>)表示TCP分片从TCP A到TCP B的离开,或者从A到B的到达。左箭头(<–)相反。省略号(…)表示仍然停留在网络上(延迟)的分片。“XXX”表示丢失或者被拒绝的分片。注释出现在圆括号中。TCP状态代表了分片(内容在每条线中间显示)离开或者到达后的状态。分片内容以缩略形式表示,包括系列号,控制位和ACK字段。其它字段如窗口,地址,长度和文本被忽略。

      TCP A                                                TCP B
    
  1.  CLOSED                                               LISTEN
   
  2.  SYN-SENT    -->                --> SYN-RECEIVED
 
  3.  ESTABLISHED <--   <-- SYN-RECEIVED
  
  4.  ESTABLISHED -->        --> ESTABLISHED
  
  5.  ESTABLISHED -->  --> ESTABLISHED


          Basic 3-Way Handshake for Connection Synchronization

                                Figure 7.

在上图的线2中,TCP A通过发送一个指示它将使用100开始的系列号码的SYN分片开始。在线3中,TCP B发送了一个SYN和它从TCP收到的分片的确认。注意,确认字段指示了TCP B现在期望侦听系列号101,确认占用系列号100的SYN。

在线4中,TCP A以包含TCP‘s的SYN包的ACK的空分片响应,而在线5,TCP A发送了一些数据。注意在线5中的系列号同线4中的系列号一致,因为ACK并不占用系列号空间(如果占用,我们将结束正在确认的ACK)。

同时发起相对复杂一些,在现图中展示。每个TCP循环从CLOSED到SYN-SENT到SYN-RECEIVED到ESTABLISHED。

     TCP A                                            TCP B
     
  1.  CLOSED                                           CLOSED
  
  2.  SYN-SENT     -->               ...
  
  3.  SYN-RECEIVED <--               <-- SYN-SENT
  
  4.               ...               --> SYN-RECEIVED
  
  5.  SYN-RECEIVED -->  ...
  
  6.  ESTABLISHED  <--  <-- SYN-RECEIVED
  
  7.               ...      --> ESTABLISHED


                Simultaneous Connection Synchronization

                               Figure 8.

三次握手的基本原则是防止老的重复连接发起导致的混乱。为了处理这个,一条特殊的控制信息,reset,被提了出来。如果正在接收的TCP正处于一个非同步状态(比如,SYN-SENT,SYN-RECEIVED),它在接收到一个可以接受的reset后返回继续监听。如果TCP处于同步状态(ESTABLISHED,FIN-WAIT-1,FIN-WAIT2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT),它放弃了连接且通知用户。我们后面会讨论这种处于“半打开(half-open)”连接下的情况。

     TCP A                                                TCP B

  1.  CLOSED                                               LISTEN

  2.  SYN-SENT    -->                ...
  
  3.  (duplicate) ...                --> SYN-RECEIVED
 
  4.  SYN-SENT    <--   <-- SYN-RECEIVED
  
  5.  SYN-SENT    -->                --> LISTEN
  
  6.              ...                --> SYN-RECEIVED

  7.  SYN-SENT    <--   <-- SYN-RECEIVED

  8.  ESTABLISHED -->       --> ESTABLISHED
   
                    Recovery from Old Duplicate SYN
                    
                               Figure 9.

作为一个从老的重复分片中恢复的简单例子,看下图9。在线3,一个老的重复SYN到达TCP B。TCP B不能断定这是一个老的重复分片,所以它正常响应(线4)。TCP A检测到ACK字段不正确就返回了一个RST(reset),该RST的SEQ字段使分片可信。TCP B在收到RST后,返回到LISTEN状态。当原来的SYN在线6最后到达,同步过程正常开始。如果线6的SYN在RST前到达,则将发生更复杂的交换(两个方向都发送RST)。

半打开(Half-Open)连接和其它不规则情况

一条已经建立的连接当TCP的一方已经在自己一端关闭或者中断连接且不知道另一端的情况,或者当连接双方由于崩溃导致失忆变成不同步,就称为“半打开”的连接。如果尝试在该连接的任何一个方向上发送数据,这个连接就会自动变成reset。但是,半打开连接被期望是不同寻常的,恢复过程仅轻微涉及。

如果在A端连接不再存在,则用户在B端在该连接发送任何数据会导致B端的TCP接收到一个reset控制信息。该信息指示B端TCP连接发生了错误,且它被期望终止连接。

假设两个用户进程A和B相互通信,这时一个崩溃发生导致了A端TCP失忆。依赖于操作系统对A端TCP的支持,有可能存在一些错误恢复机制。当TCP重新启动,A可能从最开始点启动或者从一个恢复点启动。因此,A可能会尝试重新打开连接或者在他认为打开的连接上发送数据。在后一种情况中,它会从本地(A的)TCP收到“连接未打开”的错误信息。在尝试建立连接时,A端TCP会发送一个包含SYN的分片。这个例子在下图中展示。TCP A崩溃后,用户尝试重新打开连接。同时TCP B认为连接是打开的。

      TCP A                                           TCP B
  
  1.  (CRASH)                               (send 300,receive 100)
 
  2.  CLOSED                                           ESTABLISHED
  
  3.  SYN-SENT -->               --> (??)
  
  4.  (!!)     <--      <-- ESTABLISHED
  
  5.  SYN-SENT -->               --> (Abort!!)
  
  6.  SYN-SENT                                         CLOSED
  
  7.  SYN-SENT -->               -->
  
                     Half-Open Connection Discovery
  
                               Figure 10.

当SYN在线3到达的时候,TCP B,正处于同步状态,且到来的分片在窗口之外,以一个确认响应,该确认指示了他期望听倒的下一个系列号(ACK 100)。TCP A发现这个分片没有对他发送的分片作任何确认,处于未同步状态,由于它检测到了一个半打开的连接就发送了一个reset(RST)。TCP B在线5中断了连接。TCP A继续尝试建立连接,问题就变成基本的三次握手。

另外一种有趣的情况是当TCP A崩溃时,TCP尝试在它认为是一个同步的连接上发送数据。这种情况在下图中展示。在这种情况中,从B到达A(线2)的数据由于没有连接存在不被接收,所以TCP A发送了一个RST。RST是可接受的,所以TCP B处理了该RST,然后终止了连接。

       TCP A                                              TCP B
  
  1.  (CRASH)                                   (send 300,receive 100)
  
  2.  (??)    <--  <-- ESTABLISHED
  
  3.          -->                    --> (ABORT!!)
   
  
           Active Side Causes Half-Open Connection Discovery
  
                               Figure 11.

在下图中,我们发现TCP A和B都处于被动等待SYN连接。一个老的重复分片到达TCP B(线2),触发了B的动作。一个SYN-ACK被返回(线3),并且导致了TCP A产生了一个RST(线3的ACK是不能被接受的),TCP B接受了reset,且返回到被动监听状态。

      TCP A                                         TCP B
  
  1.  LISTEN                                        LISTEN
  
  2.       ...                 -->  SYN-RECEIVED
  
  3.  (??) <--    <--  SYN-RECEIVED
  
  4.       -->               -->  (return to LISTEN!)
 
  5.  LISTEN                                        LISTEN
  
       Old Duplicate SYN Initiates a Reset on two Passive Sockets
 
                               Figure 12.

各种各样的情况都有可能,所有的这些情况遵循RST产生和处理的规则。

Reset产生

作为一条基本规则,reset(RST)在一个分片到达且明显不是当前连接的分片的任何时候必须被发送。如果还不清楚,reset不能被发送。

有三组状态:

  1. 如果连接不存在(关闭),那么reset被发送来响应任何到来分片(另外一个reset除外)。特别的,属于一个不存在的连接的SYN被这个方式拒绝。

    如果到来分片有ACK字段,reset从该分片的ACK字段提取系列号,否则reset系列号取0,ACK字段设置成系列号和到来分片的分片长度的和。连接保留在关闭(CLOSED)状态。

  2. 如果连接处于非同步状态(LISTEN,SYN-SENT,SYN_RECEIVED),到来分片对没有发送的东西进行确认(分片携带了不被接受的ACK),或者一个到来分片同连接要求的安全级别或者分隔没有严格匹配,reset被发送。

    如果我们的SYN还没有被确认且到来分片的优先级别高于要求的优先级别,则双方都提高本地优先级别(如果用户和系统允许的话)或者发送一个reset;或者如果到来分片的优先级别低于要求的优先级别,则继续,就像优先级别严格匹配一样。(如果远端TCP不能提高优先级别来匹配我们的优先级别,在下一个它发送的分片中会被检测到,且连接将会被终止)。如果我们的SYN已经被确认(可能是在这个到来的分片中),到来分片的优先级别必须同本地优先级别严格匹配,如果没有匹配,一个reset必须被发送。
    如果到来分片有一个ACK字段,reset从分片的ACK字段中提取系列号。否则,reset的系列号为0,ACK字段设置成到来分片系列号和分片长度的和。连接维持同一状态。

  3. 如果连接处于同步状态(ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT),任何不被接受的分片(在系列号窗口之外或者不被接受的确认号码)必须仅发出一个包含当前发送队列号码和指示下一个期望被收到的系列号的确认的确认分片,且连接维持在相同的状态。

    如果到来分片同连接要求的安全级别、分隔不一样,reset被发送,连接进入到CLOSED状态。Reset从到来分片的ACK字段提取系列号。

Reset处理

在除了SYN-SENT之外的所有状态中,所有的reset(RST)分片通过检查他们的SEQ字段被验证有效。如果一个reset的系列号在窗口内,则它是有效的。在SYN-SENT状态中(一个reset作为一个初始SYN的响应被收到),如果ACK字段确认了SYN,RST是可以接受的。

RST的接收者首先验证它,然后改变状态,如果接收者处于LISTEN状态,它可以忽略RST。如果接收者处于SYN-RECEIVED状态,且之前处于LISTEN状态,则接收者返回到LISTEN状态,否则接收者终止连接然后进入CLOSED状态。如果接收者处于其它的状态,它终止连接,告知用户,进入CLOSED状态。

3.5 关闭一个连接

CLOSE是表示“我已经没有数据要发送”的操作。关闭一个全双工的连接的概念属于含糊的解释,当然,既然它不清楚如何对待连接的接收端。我们选择以一个单工方式处理CLOSE。关闭连接的用户可以继续接收直到他被告知另一端也关闭了。这样,一个程序可以在几个SENDs之后跟1个CLOSE,然后继续接收直到由于另一端关闭RECEIVE失败。我们假定TCP会通知用户另一端已经关闭,即使没有明显的RECEIVE,这样用户可以优雅地关闭他自己这端的连接。TCP将可靠地投递所有的在连接关闭前发送的缓冲,因此一个希望没有返回数据的用户只要等待监听连接被成功关闭一直到他的所有数据被目标TCP接收。用户必须保持读取他们关闭发送的连接直到TCP说明再没有数据。
最基本的三种情况:

  1. 用户通过告知TCP关闭连接发起
  2. 远端TCP通过发送FIN控制信号发起
  3. 双方用户同时关闭
  • 第一种情况:本地用户发起关闭
    在这种情况中,FIN分片可以被构建并放在外发分片队列中。从用户发起的SENDs不再被TCP接受,TCP进入了FIN-WAIT-1状态。RECEIVE在这个状态是允许了。所有之前发送的分片包括FIN分片都会被重传直到被确认。当其它TCP确认了FIN分片,且发送了它自己的FIN分片,第一个TCP可以确认这个FIN。注意一个接受到一个FIN的TCP将确认但不发送它自己的FIN,直到用户也关闭了连接。

  • 第二种情况:TCP从网络上接受到一个FIN
    如果一个未被恳求的FIN从网络上到达,接收TCP可以确认它,然后告知用户连接正在关闭。用户以CLOSE响应,在这个过程中TCP在发送完任何剩下的数据后可以发送一个FIN给另一个TCP。然后TCP等待它自己的FIN被确认后关闭连接。如果ACK没有到来,则在用户超时后连接被终止,用户也会被告知。

  • 第三种情况:双方用户同时关闭
    连接两端FIN同时被用户关闭导致FIN分片被交换。当FIN之前的所有分片被处理和确认,每个TCP可以确认它收到的FIN。双方在接收到这些ACK后将删除连接。

      TCP A                                                TCP B
 
 1. ESTABLISHED                                         ESTABLISHED
 
 2. (Close)
      FIN-WAIT-1 -->  --> CLOSE-WAIT
 
 3.  FIN-WAIT-2 <--       <-- CLOSE-WAIT
 
 4.                                                       (Close)
    TIME-WAIT   <--  <-- LAST-ACK
 
 5. TIME-WAIT   -->       --> CLOSED
 
 6. (2 MSL)
      CLOSED                                                      
 
                         Normal Close Sequence
 
                               Figure 13.
      TCP A                                                TCP B
 
 1. ESTABLISHED                                         ESTABLISHED
 
 2. (Close)                                              (Close)
       FIN-WAIT-1 -->  ... FIN-WAIT-1
                  <--  <--
                  ...  -->
 
 3.   CLOSING     -->       ... CLOSING
                  <--       <--
                  ...       -->
 
 4. TIME-WAIT                                            TIME-WAIT
      (2 MSL)                                              (2 MSL)
      CLOSED                                               CLOSED
 
                      Simultaneous Close Sequence
 
                               Figure 14.

3.6 优先级和安全性

意图是连接只允许在同两个端口要求的优先级和间隔值相等或者更高的情况下在端口间进行。
在TCP中使用的优先级和安全参数就是那些在Internet协议(IP)中定义的优先级和安全参数。在这个TCP规范中,术语“安全性/间隔(compartment)”是用来指示用于IP的安全参数,包括安全性(security),间隔(compartment),用户组(user group)和处理限制(handling resetriction)
一个有着不匹配的安全/间隔值或者较低优先级值的连接尝试必须通过发送一个reset被拒绝。由于优先级太低拒绝一个连接只发生在SYN的确认收到之后。
注意,仅操作于优先级的缺省值之上的TCP模块仍会检查到来分片的优先级,且可能提高他们用于连接的优先级。
安全参数可以被用于一个非安全环境(值指示了未分类的数据),然后在非安全环境中的主机必须准备接收安全参数,即使他们不需要发送这些参数。

3.7 数据通信

一旦连接建立,数据通过分片的交换进行通信。因为分片可能由于错误(校验和测试失败),或者网络拥挤而丢失,TCP使用了重传(经过一个超时)来确保每个分片的投递。由于网络和TCP的重传,可能会有重复分片到达。如系列号一节讨论的,TCP对分片的系列号和确认号码进行某些测试来查证可接受性。
数据发送者在变量SND.NXT中记录了下一个要使用的系列号。接收者在变量RCV.NXT中使用了期待接收的下一个系列号。数据发送者在变量SND.UNA中记录了最老的未经确认的系列号。如果数据流即刻空闲,且所有发送的数据已经被确认,则三个变量相等。
当发送者创建了一个分片并传输它的时候,发送者增加了SND.NXT。当接收者接受了一个分片,他增加了RCV.NXT并发送了一个确认。当数据发送者接收一个确认,它增加了SND.UNA。这三个变量的差值可以用来衡量通信的延迟。变量增加的数量是分片中数据的长度。注意,一旦处于ESTABLISHED状态,所有的分片必须携带当前确认信息。
CLOSE用户调用执行了一个PUSH函数,通过这个函数,在一个到来分片中包含了FIN控制位。
重传超时(Retransmission Timeout)
由于组成internetwork系统的网络的多样性和TCP连接的大范围使用,重传超时必须被动态确定。确定重传超时的一个程序在下面给出。
一个重传超时例子程序
计算以一个特殊系列号发送一个数据八位字节和接收到覆盖那个系列号(发送分布不一定要匹配接收到的分片)的确认之间这段流逝时间。这样计算的流逝时间是往返旅行时间(RTT:Round Trip Time)。接着计算一个平滑往返旅行时间(SRTT:Smoothed Round Trip Time):
SRIT = (ALPHA * SRTT)+((1-ALPHA) * RTT)
基于这个,计算重传超时(RTO:retransmission timeout):
RTO = min[UBOUND,max[LBOUND,(BETA * SRTT)]]
这里UBOUND是超时上限(比如,1分钟),LBOUND是超时下限(比如,1秒),ALPHA是个平滑因子(比如,.8到.9),BETA是一个延迟因子(比如,1.3到2.0)
紧急信息的通信(The Communication of Urgent Information)
TCP紧急机制的目的是允许发送用户激发接收用户去接收一些紧急数据并允许接收TCP当所有的当前已知的紧急数据被用户接收的时候去指示接收用户。
这个机制允许数据流中的某个点被指派为紧急信息的结束。不管什么时候当这个点在接收TCP的接收系列号(RCV.NXT)之前,TCP必须告知用户进入“紧急模式(urgent mode)”,当接收系列号追上紧急指针,TCP必须告诉用户进入“正常模式(normal mode)。如果紧急指针在用户处于紧急模式的时候被更新,这个更新对用户是不可见的。
这个方法采用了一个在所有传输分片中传输的紧急字段。URG控制位指示了紧急字段有意义且必须被添加到分片系列号里面来产生紧急指针。如果没有这个标志,则表示没有显著的紧急数据。
要发送一个紧急指示,用户必须发送至少一个数据字节。如果发送用户同时指示了一个push,紧急信息到目的进程的立即投递被加强。
管理窗口(Managing the window)
在每个分片中发送的窗口指示了窗口发送者(数据接收者)当前准备接收的系列号的范围。通常假定这是同这个连接的当前可用数据缓冲空间相关的。
指定一个大的窗口可能会加大重传概率。如果多于可以被接受的数据到达,它将被丢弃。这将导致过多的重传,给网络和TCP增加了不必要的负载。指示一个小的窗口可以限制重传,但会在每个新的重传分片之间引入一个往返延迟。
这个机制允许TCP广告一个大的窗口,随后没有接收那么多数据,广告一个小得多的窗口。这也称为“收缩窗口”,是非常令人气馁的.坚固原则规定TCP不会自己收缩窗口,但会对另一端的TCP的这种行为有所准备。
发送TCP必须准备从用户接受并且发送至少一个八位字节的新数据即使发送窗口是0。发送TCP必须有规律地重传给接收TCP即使当窗口是0。当窗口是0时,建议重传间隔为2分钟。重传可以保证任何有一个0窗口的TCP的窗口的重新打开将会可靠地报告给另一端。
当接收TCP有一个0窗口并且分片到达,它必须仍然发送一个确认说明它下一个期待的系列号和当前窗口(0)。
发送TCP将要传输的数据包装成适合当前窗口的分片,且可以在重传队列中重新包装分片。这样的重新包装不要求,但是很有用。
在一个有着单向数据流的连接中,窗口信息将会在确认分片中携带,这些分片具有相同的系列号,因此如果他们不按顺序到达,就没有办法记录他们。
这不是一个严重的问题,但它将允许窗口信息有时临时地基于数据接收者的老的报告。一个避免这个问题的技巧是作用于携带最高的确认号码的窗口信息(也就是那些确认号码等于或者大于之前接收到的最高的确认号码)
窗口管理程序对通信性能有重要影响。下面是一些对实现者的建议。
窗口管理建议
分配一个很小的窗口导致数据需要用很多小的分片传输,这时使用尽量少的大分片可以获取更优的性能
接收者尽量避免更新窗口,直到额外分配至少达到了连接的最大可能分配的百分X(这里X可能从20到40)
发送者尽量避免等到窗口足够大才发送小分片。如果用户用信号通知了一个push功能,则数据必须被发送,即使它是个小分片。
注意确认不能被延迟,否则会导致不必要的重传。一个策略是当一个小分片到来的时候立即发送一个确认(没有更新窗口信息),然后发送另外一个带有新的窗口信息的确认,当窗口更大的时候。
查到一个零窗口,发送可能会开始将传送数据分成越来越小的分片。如果一个包含单个数据八位字节的被发送且检查到0窗口的分片被接受,它就假定当前一个八位字节的窗口是可用的。如果发送TCP仅简单地发送任何窗口不为0的时候它能发送的数据,传输数据将会分成可以代替的大的和小的分片。随着时间的推移,在接收端让窗口分片可用的临时的停顿将导致大的分片被分成小的和不那么大的分片。过一会,数据传输会以大部分小分片进行。
这里建议TCP实现需要主动尝试连接小窗口分片成为大窗口,因为管理窗口的机制在很多简单的实现中倾向于很多小的窗口。

3.8 接口(Interfaces)

当然,我们关心两组接口:用户/TCP接口和TCP/底层接口。我们有一个用户/TCP接口的相对详细的模型,但是底层协议模块的接口这里没有指定,因为它将由底层协议规范详细指定。在这个例子中,底层是IP,我们列出TCP可以使用了一些参数值。

用户/TCP接口
下面对TCP的用户命令描述尽可能地概括式的,因为每个操作系统有不同的接口。从而,我们必须警告读者,不同的TCP实现可能有不同的用户接口。但是,所有的TCP必须提供最少的一套服务接口以保证所有的TCP实现可以支持同样的层次结构。这个部分指定了所有TCP实现要求的功能性接口。

TCP 用户命令
下面的章节功能性地描述了一个用户/TCP接口。使用的符号同高级语言里面的大多数程序和接口函数相似,但这个用法不是用来排除圈套类型的服务调用(比如,SVCs,UUOs,EMTs)
下面描述的用户命令指定了TCP必须实现以支持进程间通信的基本功能。各自的实现必须定义他们自己的形式,且可以在一个简单调用中提供基本功能的结合或者子集。特别地,一些实现可能希望自第一个SEND或者RECEIVE调用中自动OPEN一个连接。
要提供进程间通信的接口,TCP不仅要接受命令,还要返回信息给他服务的进程。后一部分包括:
(a) 一个连接的的概要信息(比如,中断,远端关闭,未指定外部端口的绑定)
(b) 回复特定的用户命令指示成功或者各种类型的失败

Open
格式:OPEN(本地端口(local port),外部套接字(foreign socket),主动(active)/被动(passive)[,超时(timeout)][,优先级(precedence)][,安全性(security)/分隔(compartment)][,选项(options])–>本地连接名字(local connection name)
我们假定本地TCP知道他服务的进程的id,并且将检查进程使用指定连接的权利。依赖于TCP的实现,本地网络和源地址的TCP标识将由TCP或者底层协议(比如IP)提供。这些考虑是是安全性考虑的结果,比如没有TCP可以假扮成其它TCP,等等。类似的,没有进程可以假扮成另一个进程,除非同TCP勾结。
如果主动(active)/被动(passive)标志被置成被动,则是对LISTEN的调用,对到来的连接进行监听。一个被动的打开可以有一个完全指定的外部套接字来等待一个特定的连接或者一个未指定的外部套接字来等待任何调用,一个完全指定的被动调用可以通过后来的SEND的执行变成主动的。
一个传输控制块(TCB)被创建且部分被从OPEN命令参数得到的数据填充。
在一个主动调用命令里面,TCP将立即开始连接的同步过程(如,建立)。
超时参数,如果出现的话,允许调用者对所有的传输给TCP的数据设定超时。如果数据不在指定的时间间隔被成功投递到目的地,TCP将终止连接。现在的缺省值是5分钟。
TCP或者操作系统的某些部分将验证用户以指定的优先级或者安全性/分隔打开一个连接的权限。如果不在OPEN调用中指定优先级或者安全性/分隔,则采用缺省值。
仅当安全性/分隔信息相同且优先级等于或者高于OPEN调用所要求的优先级,TCP将接受到来的请求。
连接的优先级是OPEN调用所要的值和接收到的到来请求的值的高者,并且在连接的生命周期内固定在那个值。实现者可能希望给用户优先级协商的控制。比如,用户可能允许指定优先级必须严格匹配,或者任何提高优先级的尝试必须由用户确认。
本地连接名字被TCP返回给用户。该名字可以用来作为由《本地套接字,外部套接字》对定义的连接的简称。

Send
格式:SEND(本地连接名字(local connection name),缓冲地址(buffer address),字节数量(bye count),PUSH标志,URGENT标志[,超时(timeout)])
这个调用导致了包含在指定用户缓冲的数据在指定连接被发送。如果连接还没有打开,SEND被认为是一个错误。有些实现可能会允许用户先SEND;在这种情况下,将会自动调用OPEN。如果调用进程没有权利使用这个连接,返回一个错误。
如果设置了PUSH标志,数据必须立刻被传送给接收者,且PUSH位将被设置于从缓冲中创建的最后一个TCP分片。如果PUSH标志没有设置,数据可以同之后的SEND调用的数据结合在一起,以提高传输效率。
如果设置了URGENT标志,发送给目的IP的分片将设置紧急指针。如果紧急指针指示紧急指针之前的数据还没有被接收进程消耗掉的话,接收TCP将向接收进程标记紧急条件。Urgent的目的是激发接收者处理紧急数据,并指示接收者什么时候所有当前已知的紧急数据已经被接收。发送用户标识紧急的次数不一定同接收用户被通知紧急数据出现的次数相等。
如果没有在OPEN中指定外部socket,但是连接建立了(比如,因为一个正在监听的连接由于外部分片到达本地socket变得特殊),则指定的缓冲被发送到隐含的外部socket。以未指定的外部socket使用OPEN的用户可以在不曾明确知道外部soeket的地址的情况下使用SEND。
但是,如果SEND在外部socket确定之前被调用,将返回一个错误。用户可以使用STATUS调用来判断连接的状态。在某些实现中,TCP在一个未指定的socket被绑定时可能通知用户。
如果指定了超时,这个连接的当前用户超时将变成新的值。
在最简单的实现中,SEND将不会返回控制给发送进程,直到传输完成或者超时。但是,这种简单的方法可能会导致死锁(比如,连接的两端可能会在做任何RECEIVE之前尽力去SEND)和提供低性能,所以不被推荐。一个比较成熟的实现是立即返回,允许进程同网络I/0同时运行。多个SENDs以先到先服务的顺序被服务,因此TCP将那些它不能马上服务的接口调用放到队列中。我们暗中指定了一个用户接口,通过这个接口,SEND后来会从服务TCP发送某个种类的信号量或者伪中断。一个可以替代的方法是立即返回一个响应。比如,SENDs可能会立即返回一个本地的确认,即使要发送的分片还没有被远端TCP确认。我们乐观地假定事件成功。如果我们错误了,连接将由于超时关闭。在这种同步方式的实现中,也将会有一些异步信号量,但这些信号量将由连接自己处理,而不是由特定的分片或者缓冲。
为了进程能够在不同的SENDs中区分错误或者成功指示,返回缓冲地址和SEND请求的响应编码是比较合适的。将在后面进行讨论的TCP-to-user信号量指示了必须返回给调用进程的信息。

Receive
格式:RECEIVE(本地连接名字(local connection name),缓冲地址(buffer address),字节数(byte count)-à字节数(byte count),紧急标志(urgent flag),push标志(push flag)
这个命令分配了一个接收缓冲同指定连接联系在一起。如果之前没有OPEN或者调用进程没有权利使用这个连接,会返回一个错误。
在最简单的实现中,控制权将不会返回给调用程序,除非缓冲满了,或者错误发生了,但是这种方式很容易引起死锁。一个比较成熟的实现是允许几个RECEIVEs同时出现。当分片到达的时候,相应的缓冲就被填充。这个策略允许以更加复杂的架构(可能是异步的)来通知调用程序PUSH已经被发送或者缓冲填满的代价来增加吞吐量。
如果足够充满缓冲的数据在PUSH发现之前到达,PUSH标志将不会被设置来响应RECEIVE。缓冲将填充尽可能多的数据。如果PUSH标志在缓冲满之前发现,缓冲将在部分满的情况下返回,并指示PUSH标志。
如果有紧急数据,紧急数据一到达,将通过一个TCP-to-user的信号通知用户。然后接收用户就进入紧急模式(urgent mode)。如果URGENT标志打开,额外的紧急数据保留着。如果URGENT标志关闭,RECEIVE的调用返回所有的紧急数据,用户可能现在离开紧急模式(urgent mode)。注意跟在紧急指针后面的数据(非紧急数据)不能在同一块缓冲里面同前面的紧急数据被投递给用户,除非边界被清晰地标注。
为了区分几个显著的RECEIVEs以及照顾到缓冲没有被完全充满的情况,缓冲指针和一个指示真正收到的数据的真实长度的字节数同返回码一起返回。
一个RECEIVE的替代的实现可能由TCP分配缓冲,或者TCP可以同用户共享一个环型缓冲。

Close
格式:CLOSE(本地连接名字(local connection name))
这个命令将关闭指定的连接。如果连接没有打开或者调用进程没有权利使用该连接,将返回一个错误。关闭连接是个优雅的操作,所有的那些显著的SENDs将会被发送(和重传),直到所有都被服务。因此,在一个CLOSE之后进行几次SEND调用是可以被接收的,且期望所有的数据被发送到目的地。也要清楚用户必须继续在一个CLOSING的连接上RECEIVE,因为另一端可能正在发送剩下的数据。因此,CLOSE意思是“我没有数据要发送”,而不是“我不再接收任何数据”。有可能正在关闭的一端无法在超时前清除所有的数据(如果用户级别协议没有经过仔细考虑的话)。在这种情况下,CLOSE转入ABORT,正在关闭的TCP放弃。
用户可能在任何时候主动CLOSE连接,或者响应从TCP到来的各种提示(比如,远端关闭执行了,传送超时,目的地无法到达)
因为关闭一个连接需要同外部TCP通信,连接可以保留在CLOSING状态一小段时间。在TCP回复CLOSE命令前尝试重新打开一个连接将导致错误响应。
关闭也暗示了一个push功能。

Status
格式:STATUS(本地连接名字(local connection name))–> 状态数据
这是依赖于实现的用户命令,可以被排除,没有不利的影响。返回的信息通常来自于同连接联系的TCB。
这个命令返回一个数据块,包含下面的信息:
本地socket(local socket),
外部socket(foreign socket),
本地连接名字(local connection name),
接收窗口(receive window),
发送窗口(send window),
连接状态(connection state),
等待确认的缓冲的数目(number of buffers awaiting acknowledgment),
等待接收的缓冲数目(number of buffers pending receipt),
紧急状态(urgent state),
优先级(precedence),
安全性/分隔(security/compartment)
传送超时(transmission timeout)
基于连接的状态或者实现本身,有些信息可能无法获取或者没有意义。如果调用进程没有权利使用这个连接,将返回一个错误。这防止了未授权进程获取关于连接的信息。

Abort
格式:ABORT(本地连接名字(local connection name))
这个命令将放弃所有悬而未决的SENDs和RECEIVEs,TCB被清除,特殊的RESET信息将被发送给连接另一端的TCP。依赖于实现,用户可能接收到每个显著的SEND或者RECEIVE的指示,或者可能只是收到一个ABORT确认。
TCP-to-User信息
假定操作系统为TCP提供了一个异步发送信号给用户程序的方法。当TCP发信号给用户程序的时候,一些信息传给了用户。在规范中,信息通常会是一个错误信息。在其它情况下,有可能是相关于执行SEND或者RECEIVE或者其它用户调用的完成情况的信息。
下面的信息被提供:

本地连接名字(Local Connection Nmae)                   总是提供
响应字串(Resonse String)                               总是提供
缓冲地址(Buffer Address)                               Send & Receive
字节个数(Byte Cound(Counts bytes received))            Receive
Push标志                                              Receive
Urgent标志                                           Receive

TCP/底层协议接口
TCP调用一个底层协议模块来在网络上接收和发送信息。在ARPA 互联网系统中,底层协议是Internet协议(IP)
如果底层级别的协议是IP,它提供了服务类型(type of service)和生存时间(time to live)等参数。TCP对于这些参数使用了下列设置:
Type of Service = Precedence(优先级):routine(常规),Delay(延迟):normal(正常),Throughput(吞吐量):normal(正常),Reliability(可靠性):normal(正常);or 00000000
Time to Live(生存时间) = 1分钟,或者00111100
注意假定最大分片生命周期是2分钟。这里我们明确要求分片如果在1分钟内不能被投递,它必须被销毁。
如果底层协议是IP(或者其它提供这个特性的协议),且使用源地址选路,接口必须允许选路信息进行通信。这特别重要,因为这样保证在校验和中使用的源地址和目的地址是初始的源和最后的目的地址。保留返回路径来响应连接请求也很重要。
任何底层协议需要提供源地址,目的地址和协议字段,以及一种确定“TCP长度”的方式,既可以提供功能性的等同IP服务,也可以在TCP检验和中使用。

3.9 事件处理(Event Processing)

本章节描述的处理是一种可能实现的例子。其它实现可能在处理顺序上略有不同,但是他们仅在细节上有不同的地方,而不是本质上。
TCP的活动可以被概括为对事件的响应。发生的事件可以分为三种类型:用户调用(user calls),分片到达(arriving segments),和超时(timeouts)。本章节描述TCP响应这些事件所做的处理。在很多情况下,处理需要依赖于连接的状态。
发生的事件:
用户调用
OPEN
SEND
RECEIVE
CLOSE
ABORT
STATUS
到来分片
SEGMENT ARRIVES
超时
用户超时(USER TIMEOUT)
重传超时(RETRANSMISSION TIMEOUT)
时间等待超时(TIME-WAIT TIMEOUT)
TCP/用户接口的模型是用户命令接收到一个立即返回且可能有一个通过事件或者伪中断的延时响应。在下面的描述中,术语“信号(signal)”意味着导致了一个延时响应。
错误的响应以字符串的形式给出。比如,执行一个不存在的连接的命令收到“error:connection not open”。
请注意下面所有同系列号,确认号码,窗口等相关所有算法,都是对系列号空间大小进行模2**32。同时注意”=<”标识小于或者等于(模2**32)。
一个处理到来分片的自然的方式是想像他们首先测试是否是正确的系列号码(比如,他们的内容在系列号空间上是否位于期望的“接收窗口”范围内)然后他们通常被放入队列中,以系列号顺序被处理。
当一个分片同其它已经接收到的分片交迭在一起,我们重建分片,仅包含新的数据,然后调整头部字段以保持一致。
注意如果没有提到状态改变,TCP停留在同一个状态。

OPEN调用
CLOSED状态(如,TCB不存在)
创建一个新的传输控制块(TCB)来保存连接状态信息。填充本地socket标识,外部 socket,优先级,安全性/分隔(compartment)和用户超时信息。注意有些外部socket可能在一个被动的OPEN调用里没有被指定,且将在到来SYN分片的参数里面被填充。允许用户验证所要求的安全性和优先级,如果不满足返回“error: precedence not allowed”或者“error:security/compartment not allowed“。如果是被动的,进入LISTEN状态,返回。如果是主动的,且外部socket没有被指定,返回”error: foreign socket unspecified“;如果是主动的,且外部socket指定了,发起一个SYN分片。选择一个初始的发送系列号码(ISS:initial send sequence number)。一个形式的SYN分片被发送。设置SND.UNA成ISS,SND.NXT为ISS+1,进入SYN-SENT状态,返回。
如果调用者没有访问指定的本地socket的权利,返回“错误:连接对该进程非法(connection illegal for this process)”。如果没有空间创建一个新的连接,返回”错误:资源不足(insufficient resources)”。
LISTEN状态
如果是主动方式且指定了外部socket,则将连接从被动改成主动,选择一个ISS。发送一个SYN分片,设置SND.UNA为ISS,SND.NXT为ISS+1。进入SYN-SENT状态。同SEND联系在一起的数据可以同SYN分片一起发送或者放到队列中,在进入ESTABLISHED状态后发送。如果在命令中包含紧急位,紧急位必须同该命令的数据分片一起被发送。如果没有空间来将请求放入队列,响应”错误:资源不足(insufficient
resources)”。如果外部socket没有指定,返回“错误:外部socket未指定(foreign socket unspecified)”
SYN-SENT STATE
SYN-RECEIVED STATE
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
返回”错误:连接已经存在(connection already exists)”.

SEND调用
CLOSED状态(比如,TCB不存在)
如果用户没有访问这个连接的权限,返回”error:connection illegal for this process”.
否则,返回”error:connection does not exist”.
LISTEN状态
如果指定了外部socket,则将连接从被动改成主动,选择一个ISS。发送一个SYN 分片,将SND.UNA设置成ISS,SND.NXT设置成ISS+1。进入SYN-SENT状态。
同SEND联系的数据可以同SYN分片一起发送,或者放到队列中,进入
ESTABLISHED状态后发送。如果命令中要求了紧急位,紧急位必须同命令的数据分片一起发送。如果没有空间将请求放到队列中,响应“error:insufficient resources”。
如果外部socket未指定,返回”err:foreign socket unspecified”。
SYN-SENT状态
SYN-RECEIVED状态
将数据放到队列中,进入ESTABLISHED状态后发送。如果队列中没有空间,响应”error:insufficient resources”。
ESTABLISHED状态
CLOSE-WAIT状态
将缓冲组装成分片,发送该分片和一个确认(确认值=RCV.NXT)。如果没有足够的空间来记录这个缓冲,简单地返回”error:insufficient resources”。
如果设置了紧急标志,则SND.UP<-SND.NXT-1,并在外出分片中设置紧急指针。
FIN-WAIT-1 状态
FIN-WAIT-2状态
ClLOSING状态
LAST-ACK状态
TIME-WAIT状态
返回”error:connection closing”,不服务请求。

RECEIVE调用
CLOSED状态(比如,TCB不存在)
如果用户没有访问这个连接的权限,返回”error:connection illegal for this process”. 否则,返回”error:connection does not exist”.
LISTEN状态
SYN-SENT状态
SYN-RECEIVED状态
放到队列中,等到TCB进入ESTABLISHED状态后处理。如果队列中没有空间放置该请求,响应”error: insufficient resource”
ESTABLISHED状态
FIN-WAIT-1 状态
FIN-WAIT-2状态
如果没有充足的分片在队列中来满足请求,将请求放到队列中。如果没有队列空间来记住RECEIVE,响应 ”error: insufficient resource”. 重新组装在队列中的到来分片,放到接收缓冲中,返回给用户。如果发现PUSH标志,标记“push seen”
如果RCV.UP在当前传给用户的数据之前,通知用户紧急数据的存在。
当TCP负起了投递数据给用户的责任,必须通过发送一个确认来告诉发送者。确认的组成在下面处理到来分片中描述。
CLOSE-WAIT状态
因为远端已经发送了FIN,RECEIVEs必须被已经在手上的文本满足,但不投递给用户。如果没有文本等待投递,RECEIVE将获得“error:connection closing “响应。否则,任何还保留的文本可以用来满足RECEIVE。
CLOSING 状态
LAST-ACK 状态
TIME-WAIT状态
返回”error:connection closing”

CLOSE调用
CLOSED状态(如,TCB不存在)
如果用户没有权限访问这个连接,返回“error:connection illegal for this process”.
否则,返回”error:connection does not exist”。
LISTEN状态
任何显著的RECEIVEs都会返回“error:closing”响应。删除TCB,进入CLOSED状态,返回
SYN-SENT状态
删除TCB,返回”error:closing”响应给任何队列中的SENDs,或者RECEIVEs。
SYN-RECEIVED状态
如何没有SENDs被发起且没有悬而未决的数据要发送,则组装一个FIN分片并发送它,然后进入FIN-WAIT-1状态,否则放到队列中,在进入ESTABLISHED后处理。
ESTABLISHED状态
放到队列中,在所有的SENDs组装发送后,组装一个FIN分片并发送它。任何情况下,进入FIN-WAIT-1状态。
FIN-WAIT-1状态
FIN-WAIT-2状态
严格地说,这是一个错误,将收到”error:connection closing”响应。一个“ok”响应也可以被接受,只要第二个FIN没有被发送(但第一个FIN可能被重传)
CLOSE-WAIT状态
将请求放到队列中,直到所有之前的SENDs被组装成分片,然后发送一个FIN分片,进入CLOSING状态。
CLOSING状态
LAST-ACK状态
TIME-WAIT状态
响应“error:connection closing”

ABORT调用
CLOSE状态(比如,TCB不存在)
如果用户没有权限访问这个连接,返回“error:connection illegal for this process”.
否则,返回”error:connection does not exist”。
LISTEN状态
任何显著的RECEIVEs都会返回“error:closing”响应。删除TCB,进入CLOSED状态,
返回
SYN-SENT状态
给所有的队列中的SENDs和RECEIVEs发送“connection reset”通知,删除TCB,进入CLOSED状态,返回
SYN-RECEIVED
ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT状态
发送一个reset分片:

给所有的队列中的SENDs和RECEIVEs发送“connection reset”通知.所有等待传输(除了上面所述的RST)和重传的分片被清空,删除TCB,进入CLOSED状态,返回。
CLOSING
LAST-ACK
TIME-WAIT
响应“ok”,删除TCB,进入CLOSED状态,返回

STATUS调用
CLOSED状态(如,TCB不存在)
如果用户没有权限访问这个连接,返回“error:connection illegal for this process”.
否则,返回”error:connection does not exist”。
LISTEN状态
返回”state=LISTEN”,返回TCB指针
SYN-SENT 状态
返回”state=SYN-SENT”,返回TCB指针
SYN-RECEIVED状态
返回”state=SYN-RECEIVED”,返回TCB指针
ESTABLISHED状态
返回”state=ESTABLISHED”,返回TCB指针
FIN-WAIT-1状态
返回”state=FIN-WAIT-1”,返回TCB指针
FIN-WAIT-2状态
返回”state=FIN-WAIT-2”,返回TCB指针
CLOSE-WAIT状态
返回”state=CLOSE-WAIT”,返回TCB指针
CLOSING状态
返回”state=CLOSING”,返回TCB指针
LAST-ACK状态
返回”state=LAST-ACK”,返回TCB指针
TIME-WAIT状态
返回”state=TIME-WAIT”,返回TCB指针

分片到达
1)如果处于CLOSED状态(如TCB不存在),则
所有到来分片的数据被丢弃。包含RST的到来分片被丢弃。不包含RST的到来分片将导致RST作为响应被发送。确认和系列号字段值被选择用来使reset系列号可被发送分片的TCP接受。
如果ACK位关闭,系列号0被使用

如果ACK位打开

2)如果处于LISTEN状态,则
第一步,检查下 RST
一个到来的RST必须被忽略,返回
第二步,检查下ACK
任何在连接仍然处于LISTEN状态下到来的确认是错误的。一个可以接受的reset分片必须为任何一个到来的ACK产生分片形成。RST格式如下:

返回
第三步,检查SYN
如果设置了SYN位,检查安全性。如果到来分片的安全性(security)/分隔(compartment)没有同TCB的安全性和分隔完全匹配,则发送一个reset并返回。

如果SEG.PRC大于TCB.PRC,则如果用户允许,系统设定TCB.PRC=SEG.PRC,
如果不允许,则发送一个reset,返回。

如果SEG.PRC小于TCB.PRC则继续。
设定RCV.NXT为SEG.SEQ+1,IRS设置成SEG.SEQ,其它的控制或者文本被放到队列中以后处理。ISS必须被选择,一个如下形式的SYN分片被发送:

SND.NXT被设置成ISS+1,SND.UNA设置成ISS。连接状态必须被改成SYN-RECEIVED.注意任何其它的到来控制或者数据(同SYN结合)将在SYN-RECEIVED状态被处理,但是不用重复处理SYN和ACK。如果listen没有被完全指定(如,外部socket没有完全指定),则未指定字段现在必须被填充。
第四步,其它文本或者控制
任何其它控制或者文本产生分片(不包括SYN)都有ACK,则会被一个ACK处理丢掉。一个到来的RST分片不能是合法的,因为它不可能是为了响应任何这个连接的化身发送的。所以你不太可能收到一个RST分片,但如果收到了,丢弃分片,返回。
3)如果处于SYN-SENT状态,则
第一, 检查ACK位
如果设置了ACK位
如果SEG.ACK=SND.NXT,发送一个reset(除非设置了RST位,如果是这样的话,丢弃分片,返回 )

并且丢弃那个分片,返回。
如果SND.UNA= 第二, 检查RST位
如果设置了RST位
如果ACK是可以接受的,则发信号通知用户”error:connection reset”,丢弃分片,进入CLOSED状态,删除TCB,返回。否则(没有ACK)丢弃分片返回。
第三, 检查安全性和优先级
如果分片的安全性/分隔同TCB的安全性/分隔没有完全匹配,发送一个 reset
如果有一个 ACK

否则

如果有一个 ACK
分片的优先级必须同TCB的优先级匹配,如果不匹配,发送一个 reset

如果没有 ACK
分片的优先级高于TCB的优先级,则如果用户允许,系统就提高TCB的优先级到分片的优先级,如果不允许提高优先级,就发送一个 reset

如果分片的优先级小于TCB的优先级则继续
如果发送了reset,丢弃分片,返回
第四, 检查SYN位
这一步只有当ACK是ok的时候才需要,或者当没有ACK,且分片不包含一个RST。
如果SYN位打开,且安全性/分隔和优先级可以被接受,则设置RCV.NXT为SEG.SEQ+1,设置IRS为SEG.SEQ。SND.UNA被提高到等于SEG.ACK(如果有一个ACK),且被确认过的在重传队列的任何分片必须被移走。
如果SND.UNA>ISS(我们的SYN已经被确认),改变连接状态到ESTABLISHED,组装一个ACK分片
然后发送它。在队列中等待重传的数据或者控制可以被包括在里面。如果分片中有其它控制或者文本,则在下面的第六步被处理(在第六步中会检查URG位),否则返回
否则进入SYN-RECEIVED,组装一个SYN,ACK分片

然后发送它。如果分片中有其它的控制或者文本,放到队列中,等到ESTABLISHED状态后进行处理,返回。
第五, 如果SYN和RST位都没有被设置,则丢弃分片,返回

4)否则,
第一步,检查系列号
SYN-RECEIVED
ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT
CLOSING
LAST-ACK
TIME-WAIT状态
分片按系列号顺序被处理。对到来分片进行初始测试以丢弃老的复制分片,但进
一步的处理以SEG.SEQ顺序进行。如果分片的内容跨越了老的分片和新的分片的
边界,则只有新的部分必须被处理。
对到来分片,有4种可接受性测试:
分片接收测试

长度         窗口   
-------        --------     ------------------------------------------------------------------
0            0         SEG.SEQ = RCV.NXT
0            >0        RCV.NXT=0           0         不能接受
>0           >0       RCV.NXT=

如果RCV.WND是0,则不能接受分片,但是合法的ACKs,URGs和RSTs例外。
如果到来分片是不被接受的,必须发送一个确认进行响应(除非设置了RST位,如果这样的话,丢弃分片并返回):

发送确认以后,丢弃不能被接受的分片并返回。
接下来的例子假定分片是一个理想化的分片,它开始于RCV.NXT,没有超过窗口。可以通过去掉任何位于窗口之外的部分(包括SYN和FIN)对真正的分片进行剪裁以满足这个假设,且仅当分片开始于RCV.NXT时做进一步的处理。开始于高一些的系列号的分片留到以后进行处理。
第二步:检查RST位
SYN-RECEIVED状态
如果设定了RST位
如果连接是由一个被动的OPEN触发(比如,从LISTEN状态变更过来),则将该连接返回到LISTEN状态并返回。不需要通知用户。如果连接是通过一个主动的OPEN触发(比如,从SYN-SENT状态转化过来),则连接被拒绝,告知用户“connection refused”.在上面两种情况中的任何一种,所有在重传队列的分片必须被从队列中移走。在主动OPEN的情况中,进入CLOSED状态,删除TCB,返回。
ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT
如果设置了RST位,则任何显著的RECEIVEs和SEND都会收到“reset”响应。所有分片队列都会被清空。用户也会接收一个未被恳求的“connection reset”信号。进入CLOSED状态,删除TCB,返回。
CLOSING状态
LAST-ACK状态
TIME-WAIT状态
如果设置了RST,则进入CLOSED状态,删除TCB,返回
第三步:检查安全性和优先级
SYN-RECEIVED
如果分片的安全性/分隔和优先级同TCB的安全性/分隔,优先级没有完全匹配,
发送一个reset,返回
ESTABLISHED状态
如果分片的安全性/分隔和优先级同TCB的安全性/分隔,优先级没有完全匹配,发
送一个reset,任何显著的RECEIVEs和SEND将接收到“reset”响应。所有的分片队列必须被清空。用户也会接收到一个未被期待的“connection reset”信号。进入CLOSED状态,删除TCB,返回。
注意这个检查是在系列号检查之后,以防一个老的连接的分片有不同的安全性或者优
先级,导致当前连接被终止掉。
第四步:检查SYN位
SYN-RECEIVED
ESTABLISHED
FIN-WAIT STATE-1
FIN-WAIT STATE-2
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
如果SYN在窗口内,它是一个错误,发送一个reset,任何显著的RECEIVEs和
SEND将收到“reset”响应,所有的分片队列将被清除,用户也将收到一个未被
恳求的“connection reset”信号,进入CLOSED状态,删除TCB,返回。
如果SYN不在窗口内,不会到这个步骤且在第一个步骤一个ack将被发送(系
列号检查)。
第五步,检查ACK字段
如果ACK位没有打开,丢弃分片,返回
如果ACK位打开了
SYN-RECEIVED状态
如果SND.UNA= 如果分片确认是不被接受的,组装一个reset分片

并发送它
ESTABLISHED状态
如果SND.UNASND.NXT)则发送一个ACK,丢弃分片,返回。
如果SND.UNA 注意SND.WND是从SND.UNA的一个偏移,SND.WL1记录了用来更新SND.WND的最后一个分片的系列号。这里的检查避免了使用老分片来更新窗口。
FIN-WAIT-1 状态
除了ESTABLISHED状态要求的处理,如果我们的FIN现在被确认则进入FIN-WAIT-2状态,并在那个状态中继续处理
FIN-WAIT-2状态
除了ESTABLISHED状态的处理,如果重传队列是空的,用户的CLOSE可以被确认(“OK”),但并不删除TCB
CLOSE-WAIT状态
同ESTBLISHED状态的处理相同
CLOSING状态
除了ESTABLISHED状态的处理,如果ACK确认了我们的FIN,则进入TIME-WAIT状态,否则忽略分片
LAST-ACK状态
在这个状态唯一要做的事情是我们的FIN的确认。如果我们的FIN现在被确认了,就删除TCB,进入CLOSED状态,返回
TIME-WAIT状态
这个状态能够到来的分片是远端FIN的重传。确认它,并重新启动2 MSL的超时。
第六步,检查URG位
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
如果设置了URG位,将RCV.UP设置成max(RCV.UP,SEG.UP),如果紧急指针在消耗掉的数据之前,告知用户远端有紧急数据。如果对于这个连续系列的紧急数据用户已经被告知(或者仍然处理“紧急模式”) ,不用再通知用户。
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT
这不应该发生,因为已经收到了远端的FIN。忽略URG。
第七步,处理分片文本
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
一旦处于ESTABLISHED状态,传送分片文本到用户接收缓冲就成为可能。分片的文本可以等到缓冲满或者分片为空的时候移到缓冲。如果分片为空并携带了一个PUSH标志,则当缓冲返回的时候告知用户接收到PUSH。
当TCP负责投递数据给用户的时候,它必须对数据的收到进行确认。
一旦TCP接管了数据,他提升RCV.NXT到接收的数据,并调整RCV.WND为适合于当前缓冲可能性的值,RCV.NXT和RCV.WND的总值不能被减少。
请注意3.7节的窗口管理建议
发送一个如下格式的确认:

这个确认必须同一个分片在一块,该分片如果可能必须不延迟被传送。
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
这不会发生,因为已经从远端收到了一个FIN。忽略分片文本。
第八步,检查FIN位
如果处于CLOSED,LISTEN或者SYN-SENT状态,不要处理FIN,因为SEG.SEQ
不是合法的;丢弃分片,返回
如果设置了FIN位,告知用户“connection closing”,返回给任何悬而未决的RECEIVEs
同一条信息,提高RCV.NXT到FIN,发送一个FIN的确认。注意,FIN暗示了任何
未投递给用户的分片文本的PUSH操作。
SYN-RECEIVED 状态
ESTABLISHED 状态
进入CLOSE-WAIT 状态
FIN-WAIT-1 状态
如果我们的FIN已经被确认(可能就在这个分片里面做了确认),则进入
TIME-WAIT,启动time-wait定时器,关闭其它定时器;否则进入CLOSING状

FIN-WAIT-2 状态
进入TIME-WAIT状态,启动time-wait定时器,关闭其它定时器
CLOSE-WAIT 状态
维持在CLOSE-WAIT状态
CLOSING 状态
维持在CLOSING状态
LAST-ACK状态
维持在LAST-ACK状态
TIME-WAIT状态
维持在TIME-WAIT状态,重新启动一个2 MSL time-wait超时。
然后返回。

用户超时(USER TIMEOUT)
任何状态,如果用户超时已经到达,清空队列,告知用户“error:connection aborted due
to user timeout“, 对于任何显著的调用,也返回该消息,删除TCB,进入CLOSED
状态并返回

重传超时(RETRANSMISSION TIMEOUT)
任何状态,如果重传队列中的一个分片重传超时到达,将分片再一次放到重传队列的前
面,重新初始化重传定时器,并返回

TIME-WAIT超时
如果一个连接的time-wait到达,删除TCB,进入CLOSED状态并返回。

你可能感兴趣的:(rfc)