tcp-ip TCP

来源:互联网 发布:wmf编辑软件 编辑:程序博客网 时间:2024/06/14 10:33
TCP的主要目的是在两个进程间提供可靠、安全的通信。由于这个通信是在不可靠的通信基础(IP)上实现的,所以要考虑下面几点:
  1. 基本的数据传输
    TCP可以在两个用户之间同时、双向传输连续字节流。先将数据按字节边界分割成一个个的数据包,然后通过网络传输这些数据包。TCP先将数据进行缓冲,然后再发送,何时缓冲,何时发送,由TCP的具体实现决定。
    有时,用户会要求数据被马上发送。TCP通过push功能来满足这一需求。一个push导致TCP马上发送数据,或者马上把收到的数据提交给上层。进行push的位置对用户来说是透明的,而且这一位置也不会被记录。
    TCP提供了一个PUSH标志,在接收方缓冲中,如果发现包含PUSH标志的数据,缓冲中的数据马上提交给上层,而不用管缓冲是否己满。
  2. 可靠性
    当数据丢失、重复、损坏、乱序时,TCP必须修复这些数据。传输的可靠性通过序列号和确认信息来实现。为此,发送方为字节流中的每一个字节都分配了一个序号,一个数据段的第一个字节的序号被称为该数据段的序列号。每一个被发送的字节都要求接收者回执一个确认信息(ACK),接收方在发送确认信息时,会把它下一次希望接收的数据的序列号一起发送,这个序列号称为确认序列号。接收方通过序号解决乱序和重复的问题。
    当TCP传输一段数据时,会把这段数据拷贝到重传列表中去,当收到ACK后,将数据从重传列表中删除,如果在一定时间内没收到ACK,重传数据。
    发送方为每一个包都加上了checksum,接收方对其进行检查,来识别这个包是否损坏,损坏的包进行丢弃处理。
    一个ACK不能保证数据被用户接收到了,它只是表明接收方对此做出了一个回应。
  3. 流量控制
    为进行流量控制。在每一个ACK中,接收方指定一个window大小,来告诉发送方,它所能接收的数据范围是从确认序列号开始,window大小的数据。
  4. 复用
    为实现一台机器上多个进程同时使用TCP进行传输,必须唯一标识每一个TCP连接。TCP将主机的IP地址和一个端口号组合在一起,形成一个socket。发送方和接收方的两个socket(我们称为一对socket),唯一标识了一个连接。
  5. 连接
    要实现上面提到的可靠性和流量控制,要为每个数据流保存一些状态信息,所有的这些信息,如:socket,序列号,window大小,一起构成一个连接。发送方和接收方的两个socket(我们称为一对socket),唯一标识了一个连接。
    两个进程要进行通信,TCP必须先建立连接(初始化状态信息)。当通信结束,终止连接以释放资源。双方可以在一个连接上同时进行双向传输。
    由于建立连接在不可靠的基础上进行(IP),所以需要一个握手机制来避免错误。
  6. 优先级和安全
  1. 源端口号:16位
  2. 目的端口号:16位
  3. 序列号:32位
    此段数据第一个字节的编号(除去SYN的情况)。如果是SYN,就是初始序列号(ISN),实际数据的第一个字节编号为ISN+1。
  4. 确认序列号:32位
    如果ACK标志位被设置,确认序列号就是接收方希望发送方发送的下一段数据的序列号。如果连接己建立,确认序列号都要发送。
  5. 数据偏移:4位
    TCP头部的长度(以32位为单位,就是说包含多少个32位字)。它也表明了实际数据的开始位置。TCP头部长度是32位字的整数倍。
  6. 保留(为0):6 位
  7. 控制位:6位(从左到右)
    URG:包含紧急数据
    ACK:包含确认序列号
    PSH:包含Push
    RST:Reset连接
    SYN:同步序列号(Synchronize sequence numbers)
    FIN:发送方数据传输结束
  8. Window: 16 位
    从确认序列号开始,发送方要发送的数据大小。
  9. Checksum: 16 bits
    checksum计算方法:头部和数据按16位大小划分,对每个字取补码并相加,对相加的和取补码。如果头部和数据的字节数为奇数,最后的字节用0来补齐,以满足16位字节的要求。其中补齐的位不会当做数据传输。
    checksum计算时包含位于TCP头部前面的96位的pseudo header。pseudo header用来防止误传,结构如下:
    +--------+--------+--------+--------+
    | Source Address |
    +--------+--------+--------+--------+
    | Destination Address |
    +--------+--------+--------+--------+
    | zero | PTCL | TCP Length |
    +--------+--------+--------+--------+
    zero是保留字节,为0,PTCL是协议类型。TCP Length是TCP头部长度加上数据长度的和,但是不包含12字节的pseudo header.
  10. 紧急数据指针: 16 位
    只在URG标志设置时有效。从数据段的序列号到紧急指针的偏移。紧急数据指针指向紧急数据第一个字节的序列号。
  11. 选项
    选项在TCP头部的后面,长度为8字节的整数倍。计算checksum时要包含所有的选项。
    KindLengthMeaning0-End of option list1-No-Operation44Maximum Segment SizeEnd of Option List
    00000000Kind=0

    表明选项结束,只能用在所有选项之后,不能用在每个选项之后。 只能当选项的结尾和TCP头部的结局不能重合的情况。

    No-Operation

    00000001Kind=1
    在选项之间使用,使选项边界对齐。

    Maximum Segment Size:16位
    0000001000000100max seg sizeKind=2 Length=4
    只只能在SYN中使用,如果不指定此选项,任何大小的数据段都可以。当TCP的一方要通知对方所能接收的最大数据段时,使用此选项。

    Padding: 保证TCP头部32字节对齐。值为0。

TCP状态信息
连接信息保存在TCP(Transmission Control Block)中,如:发送方和接收方的socket 号、连接的优先级和安全等级、发送缓冲和接收缓冲的指针、重传列表的指针、当前数据段的指针。还有一些额外信息要保存:

发送序列变量:
SND.UNA - send unacknowledged
SND.NXT - send next
SND.WND - send window
SND.UP - send urgent pointer
SND.WL1 - 最近使window更新的数据序列号
SND.WL2 - 最近使window更新的确认数据序列号
ISS - 发送序列号的初始化值

接收序列变量:
RCV.NXT - receive next
RCV.WND - receive window
RCV.UP - receive urgent pointer
IRS -接收序列号的初始化值

发送序列空间

                 1                            2                               3                              4
--------------------------|--------------------------|--------------------------|--------------------------
                        SND.UNA                SND.NXT               SND.UNA + SND.WND
1 - 这些数据已经被发送,并且收到了接收方的确认
2 - 这些数据已经被发送,但还没有收到接收方的确认
3 - 当有新数据要发送时,使用这里的序列号
4 - 还不充许被分配给数据的序列号

发送window就是在区域3内。

接收序列空间
                 1                            2                               3                
--------------------------|--------------------------|--------------------------
                        RCV.NXT                RCV.NXT + RCV.WND
1 - 成功接收数据并发送了确认信息
2 -当有新数据要接收时,使用这里的序列号
3 - 还不充许被分配给数据的序列号

接收window就是在区域2内。

当前数据的变量
SEG.SEQ - 序列号
SEG.ACK - 确认序列号
SEG.LEN - 长度
SEG.WND - 数据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是虚拟的,因为此时没有TCB,即没有连接。

LISTEN - 等待一个连接请求
SYN-SENT - 发送了一个连接请求,等待一个匹配的连接请求
SYN-RECEIVED - 发送了一个连接请求并且收到了一个连接请求后,等待一个确认信息
ESTABLISHED - 连接建立,可以接收和发送数据
FIN-WAIT-1 - 发送了一个关闭连接的请求,或等待对方的关闭连接请求
FIN-WAIT-2 - 等待对方的关闭连接请求
CLOSE-WAIT - 等待本地的关闭连接请求
CLOSING - 等待关闭连接的确认信息
LAST-ACK - 前面发出了一个关闭连接的请求,等待对方的确认
TIME-WAIT - 等待足够时间,确保发出的关闭连接确认信息能够到达对方
CLOSED - 没有连接存在


TCP设计的一个基本概念就是传输的每一个字节都被编号。因为每个字节都被编号,所以每个字节都能被确认。如果一个确认序列号为X,表明序列号小于X(不包含X)的字节都已经被接收到了。这一机制可直接用作重复包的检测上。数据段中在TCP头部后面的第一个字节的编号是此段数据的最小编号,后面的字节都是连续编号的。

序列号范围是有限的,从0到2**32 - 1,当序列号到达2**32时,它必须从0重新开始。

TCP必须对序列号的检查,确定下面几项:

  1. 一个确认序列号索引的数据,它们的序列号在发送方的序列号空间的区域是“己发送但还没有收到接收方的确认“。
  2. 数据段中占用的所有序列号都被确认(如:从重传队列中删除数据段)
  3. 接收的数据段中占用的序列号在接收window的范围内

当处理确认信息时,要和下面的数据进行比较:

SND.UNA = 最小的未确认序列号
SND.NXT = 如果要发送新数据,序列号的开始值
SEG.ACK = 从接收方发送过来的确认序列号 (接收方希望接收的下一个数据的序列号)
SEG.SEQ = 接收到的数据的第一个字节的序列号
SEG.LEN = 接收到的数据的长度 (包含SYN和FIN)
SEG.SEQ+SEG.LEN-1 = 接收到的数据的最后一个字节的序列号

一个可以被接受的ACK,它的确认序列号满足条件:SND.UNA < SEG.ACK =< SND.NXT。接收到的确认信息中包含确认序列号,如果在重传队列中的一段数据,它的序列号和长度的和小于此确认序列号,我们就说这段数据己经被全部确认了,它就可以从重传队列中删除了。

当数据被接收时,需要做下面的比较:

RCV.NXT = 接收方希望收到的下一个数据的序列号,也是接收window的最小边界
RCV.NXT+RCV.WND-1 = 接收方希望收到的数据的最大序列号,也是接收window的最大边界
SEG.SEQ = 接收到的数据的第一个字节的序列号
SEG.SEQ+SEG.LEN-1 = 接收到的数据的最后一个字节的序列号

接收的一段数据要合法,必须满足下面的条件:RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND 或 RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND。如果考虑到长度为0的window和长度为0的数据段,情况就变得复杂了:

LengthWindow 00SEG.SEQ = RCV.NXT0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND>00不接受>0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND 或
 RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND注意:当接收window为0时,只能接收ACK。即使接收window为0,如果数据段中包含RST和URG,TCP也必须处理。

对于序列号空间,SYN位于实际数据第一个字节的前面,FIN位于实际数据最后一个字节的后面。数据段的长度 (SEG.LEN)包含这两个数据,序列空间也要考虑它们。当一个数据段中出现SYN标志时,它的序列号(SEG.SEQ)就是SYN的序列号。

初始化序列号

一个连接通过一对socket被唯一标识。当连接被快速的关闭和打开时,上一个连接发送的数据的序列号可能和当前连接的数据的序列号重复,如何解决这一问题?我们必须保证在新的连接中使用的初始列号不能和上一个连接的相同。当一个新的连接建立时,我们要初始化一个新的32位ISN。ISN的生成依靠一个32位的时钟,它每隔4毫秒递增一次,每隔4.55小时,ISN循环一次。因为一段数据在网络中的生存期不超过MSL(Maximum Segment Lifetime),而MSL小于4.55小时,所以我们认为新的ISN是唯一的。

每个连接有发送序列号和接收序列号。ISS(The initial send sequence number)由发送方选择。IRS(initial receive sequence number)在连接建立的过程中得到。当一个连接在建立时,双方要同步各自的初始化序列号。这一过程通过发送标志为SYN的数据段来实现。

每一方都要发送自己的初始化序列号给对方,并且要得到对方的确认。每一方都要接收对方发来的初始化序列号,还要发一个确认信息给对方。

  1. A --> B SYN 我的序列号是 X
  2. A <-- B ACK 确认你的序列号是 X
  3. A <-- B SYN 我的序列号是 Y
  4. A --> B ACK 确认你的序列号是 Y

因为2和3可以在一个数据段中发送,所以这一过程又叫作3次握手。

当TCP从错误中恢复,为保证不发送重复序列号的数据,必须等待MSL的时间才能发送数据。但如果在有些情况下,如果TCP还保留着正在使用的序列号,只要保证新的序列号比它们大就可以了,根本不用等待。

在发送方,当一个数据段被建立并送入发送队列时,都要占用序列号空间。TCP中的序列号算法和重复检测都依赖于下面一个假设:在序列号从2**32回滚到0之前,所有和序列号相关联的数据都被发送并且被确认,而且所有重复的数据都从网络中消失(超过MSL被丢弃)。这样才能保证数据和序列号的唯一绑定关系。

正常情况,TCP记录下一个要发送数据的序列号和最小的等待确认的序列号,来避免使用先前被确认过的序列号。但仅这一点不能保证不产生重复的序列号,所以序列号空间被定义的非常的大,用来减少重复的概率。

总结:每一个被提交的数据段在序列空间中占用一个或多个序列号,这些被占用的序列号在MSL的时间内被标识为“忙的或被占用的”。如果连接崩溃,最后发送的数据段占用的序列号空间,可能被一个快速建立的新连接使用,这时,在接收方就可能出现重复数据包的问题。

建立连接

建立连接通过3次握手完成。这一过程可以由一方发起,另一方响应。当两边同时发起时,有可能造成冲突,这时可通过发送RST来解决。

例子1:

 TCP A TCP B1CLOSED LISTEN2SYN-SENT--> <SEQ=100><CTL=SYN> -->SYN-RECEIVED3ESTABLISHED<-- <SEQ=300><ACK=101><CTL=SYN,ACK> <--SYN-RECEIVED4ESTABLISHED--> <SEQ=101><ACK=301><CTL=ACK> -->ESTABLISHED5ESTABLISHED--> <SEQ=101><ACK=301><CTL=ACK><DATA> -->ESTABLISHED第4行,仅仅发送了一个确认信息,没有数据。第5行,发送了确认信息和数据。注意这两行的序列号和确认序列号都相同,因为ACK不占用序列空间中的序列号。

例子2:

 TCP A TCP B1CLOSED CLOSED2SYN-SENT--> <SEQ=100><CTL=SYN> ... 3SYN-RECEIVED<-- <SEQ=300><CTL=SYN><--SYN-SENT4 ... <SEQ=100><CTL=SYN> -->SYN-RECEIVED5SYN-RECEIVED--> <SEQ=100><ACK=301><CTL=SYN,ACK> ... 6ESTABLISHED<-- <SEQ=300><ACK=101><CTL=SYN,ACK> <--SYN-RECEIVED7 ... <SEQ=101><ACK=301><CTL=ACK> -->ESTABLISHED
在建立连接的过程中有可能产生重复的SYN,为避免冲突,提供了RST功能。如果接收方在非同步状态 (如:SYN-SENT, SYN-RECEIVED)时,接收到了RST,它将返回到LISTEN状态。如果TCP在同步状态 (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT)时,接收到了RST,它将终止连接并通知用户。
 TCP A TCP B1CLOSED LISTEN2SYN-SENT--> <SEQ=100><CTL=SYN> ... 3(duplicate)... <SEQ=90><CTL=SYN> -->SYN-RECEIVED4SYN-SENT<-- <SEQ=300><ACK=91><CTL=SYN,ACK> <--SYN-RECEIVED5SYN-SENT--> <SEQ=91><CTL=RST> -->LISTEN6 ... <SEQ=100><CTL=SYN> -->SYN-RECEIVED7SYN-SENT<-- <SEQ=400><ACK=101><CTL=SYN,ACK> <--SYN-RECEIVED8ESTABLISHED--> <SEQ=101><ACK=401><CTL=ACK> -->ESTABLISHED
第3行,一个重复SYN到达了B,B不知道它是重复的,返回一个确认信息 (行4)。A检测到这个ACK有错误,返回一个RST。B接收到RST,返回到LISTEN状态。

第6行,正常的SYN到达,连接建立。如果行6的SYN在RST之前到达,更复杂的情况发生了,有可能两边都会发送RST。

Half-Open连接和其它异常情况

如果一个连接的一方关闭或终止了连接但是没有通知另一方,或者两边由于系统崩溃或内存耗尽变得不同步,就称为half-open。如A连接关闭了,B发送数据到A,B将收到一个RST信息。B就知道有错误发生,它就终止此连接。

例子:A和B想到通信,A崩溃后进行了恢复操作,然后试图向打开连接或通过连接发送一些数据。当发送数据时,收到了错误“本地连接无法打开”。A然后尝试建立连接,向B发送SYN。在这一过程中,B始终认为连接是正常的。

 TCP A TCP B1(CRASH)(send 300,receive 100) 2CLOSED ESTABLISHED3SYN-SENT--> <SEQ=400><CTL=SYN> -->(??)4(!!)<-- <SEQ=300><ACK=100><CTL=ACK> <--ESTABLISHED5SYN-SENT--> <SEQ=100><CTL=RST> -->(Abort!!)6SYN-SENT CLOSED7SYN-SENT--> <SEQ=400><CTL=SYN> --> 
第3行,当SYN到达,B发现数据超出了window,回执的确认信息指明下一个期望的序列号(ACK 100)。A收到这个确认信息后,发现不同步产生了,发送RST。B退出(行5)。A开始进行3次握手建立连接。

上面的例子,当B向A发送数据时(行2),A发送RST。B退出。

 TCP A TCP B1(CRASH)(send 300,receive 100) 2(??)<-- <SEQ=300><ACK=100><DATA=10><CTL=ACK>ESTABLISHED3 --> <SEQ=100><CTL=RST> -->(ABORT!!)

例子:A和B都在等待SYN建立连接。第2行,一个重复SYN到达B。B回应了SYN-ACK,然后A回应了RST。B接收到RST,回到LISTEN状态。

 TCP A TCP B1LISTEN LISTEN2 ... <SEQ=Z><CTL=SYN> -->SYN-RECEIVED3(??)<-- <SEQ=X><ACK=Z+1><CTL=SYN,ACK>SYN-RECEIVED4 --> <SEQ=Z+1><CTL=RST>(return to LISTEN!)5LISTEN LISTEN

Reset的产生

  1. 一个连接不存在(CLOSED),但是收到一个数据段(RST除外),TCP将回应一个RST。如:一个连接不存在,通过SYN请求建立连接,TCP将回应一个RST来拒绝这个请求。
    如果收到的数据段包含ACK,RST使用此数据段的确认序列号作为自己的序列号。否则,RST的序列号为0,确认序列号为收到的数据段的序列号加上其长度。连接仍然为CLOSED状态。
  2. 连接为非同步状态 (LISTEN, SYN-SENT, SYN-RECEIVED),接收到的数据包含一个无效的响应(对还没有发送的数据进行确认)或都收到的数据的安全级别不对,接收方回应一个RST。
    我们发送了一个SYN但还没确认,这时收到一段数据。它的优先级高于期望的优先级,此时或者提高本地的优先级(如果系统和用户允许)或都发送一个RST。如果收到的数据优先级比我们的低,就当作优先级匹配来处理 (如果对方的优先级不能提高以匹配我们的优先级,当我们发送下一个数据段时会被检测到,此时将关闭连接)。 如果我们发出的SYN被确认 (如:是在这个数据段中被确认),优先级必须匹配,不然发送一个RST。
    如果收到的数据段包含ACK,RST使用此数据段的确认序列号作为自己的序列号。否则,RST的序列号为0,确认序列号为收到的数据段的序列号加上其长度。连接仍然为CLOSED状态。
  3. 连接为同步状态(ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT), 无效的数据 (序列号不在接收window范围内或确认序列号出错)必须产生一个空的确认数据段,包含当前的发送序列号和下一个期望接收的序列号,此时连接状态不变。如果接收到的数据的安全等级,优先级不匹配,发送一个RST,这个RST的序列号为收到数据的确认序列号。

除了处在SYN-SENT状态,所有的RST数据段,如果它们的序列号在window的范围,则有效。在SYN-SENT状态(收到的RST是对SYN的响应),如果它的ACK表明是对发送的SYN的一个响应,则有效。

收到一个RST后,先验证它,然后改变TCP状态。如果当前状态为LISTEN,忽略。当前状态为SYN-RECEIVED,如果先前的状态为LISTEN,返回到LISTEN状态,否则关闭连接回到CLOSED状态。当前状态为其它,关闭连接回到CLOSED状态。

关闭连接

CLOSE意思为“我没有数据要发送了”。用户进行CLOSE操作后,还会继续RECEIVE,一直到对方也进行了CLOSED操作。TCP在收到CLOSED命令后,会把当前发送缓冲中的数据全部发送。关闭连接有3种情况:

  1. 用户主动告诉TCP去CLOSE连接
    此时,一个FIN被放到发送队列中,TCP将不再发送数据。此时进入FIN-WAIT-1状态,此状态下RECEIVE还是被允许的。在发送队列中的数据(包括FIN)都会被发送并等待ACK。
  2. 收到一个FIN
    如果收到一个FIN,TCP对它进行一个确认(ACK),然后通知用户连接关闭。如果用户调用CLOSE,TCP将FIN放到发送队列,然后将所有的数据发送。然后TPC等待对FIN的确认,如果等到了,关闭连接,如果没等到,终止连接(abort)并通知用户。
  3. 双方同时CLOSE
    同时关闭,双方都收到一个FIN,都要对收到的FIN进行确认(ACK),然后双方关闭连接。
一般关闭
 TCP A TCP B1ESTABLISHED ESTABLISHED2(Close)FIN-WAIT-1--> <SEQ=100><ACK=300><CTL=FIN,ACK> -->CLOSE-WAIT3FIN-WAIT-2<-- <SEQ=300><ACK=101><CTL=ACK> <--CLOSE-WAIT4(Close)TIME-WAIT<-- <SEQ=300><ACK=101><CTL=FIN,ACK> <--LAST-ACK5TIME-WAIT--> <SEQ=101><ACK=301><CTL=ACK> -->CLOSED6(2 MSL)CLOSED  

同时关闭

 TCP A TCP B1ESTABLISHED ESTABLISHED2(Close)
FIN-WAIT-1
--> <SEQ=100><ACK=300><CTL=FIN,ACK>...
<-- <SEQ=300><ACK=100><CTL=FIN,ACK><--
... <SEQ=100><ACK=300><CTL=FIN,ACK>-->(Close)
FIN-WAIT-13CLOSING--> <SEQ=101><ACK=301><CTL=ACK>...
<--<SEQ=301><ACK=101><CTL=ACK><--
... <SEQ=101><ACK=301><CTL=ACK>-->CLOSING4TIME-WAIT
(2 MSL)
CLOSED TIME-WAIT
(2 MSL)
CLOSED


数据传输

连接建立后,双方就可以传输数据了。数据有可能错误(checksum出错)或丢失,TCP通过重传机制来保证数据正确传输。但是重传又可能造成数据重复,TCP通过检测序列号和确认序列号来解决这一问题。

发送方用SND.NXT来记录下一个要发送的数据的序列号。接收方用RCV.NXT来记录下一个要接收的数据的序列号。发送方用SND.UNA来记录未确认数据的最小序列号。如果所有的数据都被确认并且暂时没有数据传输,这三个值是相同的。

当发送方创建一个数据段进行传输时,它会增加SND.NXT。当接收方收到一个数据时,它会增加RCV.NXT并发送一个确认信息。当发送方收到一个确认信息时,它会增加SND.UNA。这三个数据的差异程序度反映了网络传输的延迟状况。三个变量增加的值就是数据段的长度。注意,如果TCP处于ESTABLISHED状态,所有的数据段必须包含ACK信息。

当用户调用CLOSE时,会执行push功能,这时的数据段会设置FIN标志。

当接收的数据设置了紧急标志URG,TCP通知用户进入了urgent mode,当处理完由urgent pointer指向的数据后,TCP通知用户进入normal mode。

管理Window

每个数据段中的window向发送方表明了接收方当前能够接收的序列号范围。这个范围和此连接的数据缓冲相关联。

即使发送方的window为0,它也要能够从用户接收数据并发送至少一个字节的新数据。即使发送方的window为0,发送方也要完成重传的功能,此时重传间隔建议为2分钟,这是为了当window不为0时能够有足够时间通知到对方。

当接收方window为0,有数据到达时,它必须发送一个确认信息,指明期望的下一个序列号,并表明当前的window为0。

发送方将数据打包成适合当前window大小的包进行传输。处在重传队列的数据有可能会被重新打包,这一点不是必须的,但有益。

TCP用户命令

Open

Format: OPEN (local port, foreign socket, active/passive [, timeout] [, precedence] [, security/compartment] [, options]) -> local connection name

We assume that the local TCP is aware of the identity of the processes it serves and will check the authority of the process to use the connection specified. Depending upon the implementation of the TCP, the local network and TCP identifiers for the source address will either be supplied by the TCP or the lower level protocol (e.g., IP). These considerations are the result of concern about security, to the extent that no TCP be able to masquerade as another one, and so on. Similarly, no process can masquerade as another without the collusion of the TCP。

If the active/passive flag is set to passive, then this is a call to LISTEN for an incoming connection. A passive open may have either a fully specified foreign socket to wait for a particular connection or an unspecified foreign socket to wait for any call. A fully specified passive call can be made active by the subsequent execution of a SEND. A transmission control block (TCB) is created and partially filled in with data from the OPEN command parameters. On an active OPEN command, the TCP will begin the procedure to synchronize (i.e., establish) the connection at once.

The timeout, if present, permits the caller to set up a timeout for all data submitted to TCP. If data is not successfully delivered to the destination within the timeout period, the TCP will abort the connection. The present global default is five minutes.

The TCP or some component of the operating system will verify the users authority to open a connection with the specified precedence or security/compartment. The absence of precedence or security/compartment specification in the OPEN call indicates the default values must be used.

TCP will accept incoming requests as matching only if the security/compartment information is exactly the same and only if the precedence is equal to or higher than the precedence requested in the OPEN call.

The precedence for the connection is the higher of the values requested in the OPEN call and received from the incoming request, and fixed at that value for the life of the connection.Implementers may want to give the user control of this precedence negotiation. For example, the user might be allowed to specify that the precedence must be exactly matched, or that any attempt to raise the precedence be confirmed by the user.

A local connection name will be returned to the user by the TCP. The local connection name can then be used as a short hand term for the connection defined by the <local socket, foreign socket> pair.

Send
Format: SEND (local connection name, buffer address, byte count, PUSH flag, URGENT flag [,timeout])

This call causes the data contained in the indicated user buffer to be sent on the indicated connection. If the connection has not been opened, the SEND is considered an error. Some implementations may allow users to SEND first; in which case, an automatic OPEN would be done. If the calling process is not authorized to use this connection, an error is returned.

If the PUSH flag is set, the data must be transmitted promptly to the receiver, and the PUSH bit will be set in the last TCP segment created from the buffer. If the PUSH flag is not set, the data may be combined with data from subsequent SENDs for transmission efficiency.

If the URGENT flag is set, segments sent to the destination TCP will have the urgent pointer set. The receiving TCP will signal the urgent condition to the receiving process if the urgent pointer indicates that data preceding the urgent pointer has not been consumed by the receiving process. The purpose of urgent is to stimulate the receiver to process the urgent data and to indicate to the receiver when all the currently known urgent data has been received. The number of times the sending user’s TCP signals urgent will not necessarily be equal to the number of times the receiving user will be notified of the presence of urgent data.

If no foreign socket was specified in the OPEN, but the connection is established (e.g., because a LISTENing connection has become specific due to a foreign segment arriving for the local socket), then the designated buffer is sent to the implied foreign socket. Users who make use of OPEN with an unspecified foreign socket can make use of SEND without ever explicitly knowing the foreign socket address.

However, if a SEND is attempted before the foreign socket becomes specified, an error will be returned. Users can use the STATUS call to determine the status of the connection. In some implementations the TCP may notify the user when an unspecified socket is bound.

If a timeout is specified, the current user timeout for this connection is changed to the new one.

In the simplest implementation, SEND would not return control to the sending process until either the transmission was complete or the timeout had been exceeded. However, this simple method is both subject to deadlocks (for example, both sides of the connection might try to do SENDs before doing any RECEIVEs) and offers poor performance, so it is not recommended. A more sophisticated implementation would return immediately to allow the process to run concurrently with network I/O, and, furthermore, to allow multiple SENDs to be in progress. Multiple SENDs are served in first come, first served order, so the TCP will queue those it cannot service immediately.

We have implicitly assumed an asynchronous user interface in which a SEND later elicits some kind of SIGNAL or pseudo-interrupt from the serving TCP. An alternative is to return a response immediately. For instance, SENDs might return immediate local acknowledgment, even if the segment sent had not been acknowledged by the distant TCP. We could optimistically assume eventual success. If we are wrong, the connection will close anyway due to the timeout. In implementations of this kind (synchronous), there will still be some asynchronous signals, but these will deal with the connection itself, and not with specific segments or buffers.

In order for the process to distinguish among error or success indications for different SENDs, it might be appropriate for the buffer address to be returned along with the coded response to the SEND request. TCP-to-user signals are discussed below, indicating the information which should be returned to the calling process.

Receive
Format: RECEIVE (local connection name, buffer address, byte count) -> byte count, urgent flag, push flag

This command allocates a receiving buffer associated with the specified connection. If no OPEN precedes this command or the calling process is not authorized to use this connection, an error is returned.

In the simplest implementation, control would not return to the calling program until either the buffer was filled, or some error occurred, but this scheme is highly subject to deadlocks. A more sophisticated implementation would permit several RECEIVEs to be outstanding at once. These would be filled as segments arrive. This strategy permits increased throughput at the cost of a more elaborate scheme (possibly asynchronous) to notify the calling program that a PUSH has been seen or a buffer filled. If enough data arrive to fill the buffer before a PUSH is seen, the PUSH flag will not be set in the response to the RECEIVE. The buffer will be filled with as much data as it can hold. If a PUSH is seen before the buffer is filled the buffer will be returned partially filled and PUSH indicated.

If there is urgent data the user will have been informed as soon as it arrived via a TCP-to-user signal. The receiving user should thus be in "urgent mode". If the URGENT flag is on, additional urgent data remains. If the URGENT flag is off, this call to RECEIVE has returned all the urgent data, and the user may now leave "urgent mode". Note that data following the urgent pointer (non-urgent data) cannot be delivered to the user in the same buffer with preceeding urgent data unless the boundary is clearly marked for the user.

To distinguish among several outstanding RECEIVEs and to take care of the case that a buffer is not completely filled, the return code is accompanied by both a buffer pointer and a byte count indicating the actual length of the data received.

Alternative implementations of RECEIVE might have the TCP allocate buffer storage, or the TCP might share a ring buffer with the user.

Close
Format: CLOSE (local connection name)

This command causes the connection specified to be closed. If the connection is not open or the calling process is not authorized to use this connection, an error is returned.

Closing connections is intended to be a graceful operation in the sense that outstanding SENDs will be transmitted (and retransmitted), as flow control permits, until all have been serviced. Thus, it should be acceptable to make several SEND calls, followed by a CLOSE, and expect all the data to be sent to the destination. It should also be clear that users should continue to RECEIVE on CLOSING connections, since the other side may be trying to transmit the last of its data. Thus, CLOSE means "I have no more to send" but does not mean "I will not receive any more." It may happen (if the user level protocol is not well thought out) that the closing side is unable to get rid of all its data before timing out. In this event, CLOSE turns into ABORT, and the closing TCP gives up.

The user may CLOSE the connection at any time on his own initiative, or in response to various prompts from the TCP (e.g., remote close executed, transmission timeout exceeded, destination inaccessible).

Because closing a connection requires communication with the foreign TCP, connections may remain in the closing state for a short time. Attempts to reopen the connection before the TCP replies to the CLOSE command will result in error responses. Close also implies push function.

Status
Format: STATUS (local connection name) -> status data

This is an implementation dependent user command and could be excluded without adverse effect. Information returned would typically come from the TCB associated with the connection. This command returns a data block containing the following information:

local 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,
and transmission timeout.

Depending on the state of the connection, or on the implementation itself, some of this information may not be available or meaningful. If the calling process is not authorized to use this connection, an error is returned. This prevents unauthorized processes from gaining information about a connection.

Abort
Format: ABORT (local connection name)

This command causes all pending SENDs and RECEIVES to be aborted, the TCB to be removed, and a special RESET message to be sent to the TCP on the other side of the connection.

Depending on the implementation, users may receive abort indications for each outstanding SEND or RECEIVE, or may simply receive an ABORT-acknowledgment.

TCP-to-User Messages

It is assumed that the operating system environment provides a means for the TCP to asynchronously signal the user program. When the TCP does signal a user program, certain information is passed to the user. Often in the specification the information will be an error message. In other cases there will be information relating to the completion of processing a SEND or RECEIVE or other user call.

The following information is provided:
Local Connection Name Always
Response String Always
Buffer Address Send & Receive
Byte count (counts bytes received) Receive
Push flag Receive
Urgent flag Receive

TCP/Lower-Level Interface

If the lower level protocol is IP it provides arguments for a type of service and for a time to live. TCP uses the following settings for these parameters:
Type of Service = Precedence: routine, Delay: normal, Throughput:
normal, Reliability: normal; or 00000000.
Time to Live = one minute, or 00111100.
Note that the assumed maximum segment lifetime is two minutes. Here we explicitly ask that a segment be destroyed if it cannot be delivered by the internet system within one minute.

If the lower level is IP (or other protocol that provides this feature) and source routing is used, the interface must allow the route information to be communicated. This is especially important so that the source and destination addresses used in the TCP checksum be the originating source and ultimate destination. It is also important to preserve the return route to answer connection requests.

Any lower level protocol will have to provide the source address, destination address, and protocol fields, and some way to determine the "TCP length", both to provide the functional equivlent service of IP and to be used in the TCP checksum.

Event Processing
The activity of the TCP can be characterized as responding to events. The events that occur can be cast into three categories: user calls, arriving segments, and timeouts. This section describes the processing the TCP does in response to each of the events. In many cases the processing required depends on the state of the connection.

Events that occur:
User Calls
OPEN
SEND
RECEIVE
CLOSE
ABORT
STATUS
Arriving Segments

SEGMENT ARRIVES
Timeouts
USER TIMEOUT
RETRANSMISSION TIMEOUT
TIME-WAIT TIMEOUT

The model of the TCP/user interface is that user commands receive an immediate return and possibly a delayed response via an event or pseudo interrupt. In the following descriptions, the term "signal" means cause a delayed response.

Error responses are given as character strings. For example, user commands referencing connections that do not exist receive "error: connection not open".

Please note in the following that all arithmetic on sequence numbers, acknowledgment numbers, windows, et cetera, is modulo 2**32 the size of the sequence number space. Also note that "=<" means less than or equal to (modulo 2**32).

A natural way to think about processing incoming segments is to imagine that they are first tested for proper sequence number (i.e., that their contents lie in the range of the expected "receive window" in the sequence number space) and then that they are generally queued and processed in sequence number order.

When a segment overlaps other already received segments we reconstruct the segment to contain just the new data, and adjust the header fields to be consistent.

Note that if no state change is mentioned the TCP stays in the same state.

OPEN Call
CLOSED STATE (i.e., TCB does not exist)

Create a new transmission control block (TCB) to hold connection state information. Fill in local socket identifier, foreign socket, precedence, security/compartment, and user timeout information. Note that some parts of the foreign socket may be unspecified in a passive OPEN and are to be filled in by the parameters of the incoming SYN segment. Verify the security and precedence requested are allowed for this user, if not return "error: precedence not allowed" or "error: security/compartment not allowed." If passive enter the LISTEN state and return. If active and the foreign socket is unspecified, return "error: foreign socket unspecified"; if active and the foreign socket is specified, issue a SYN segment. An initial send sequence number (ISS) is selected. A SYN segment of the form <SEQ=ISS><CTL=SYN> is sent. Set SND.UNA to ISS, SND.NXT to ISS+1, enter SYN-SENT state, and return.

If the caller does not have access to the local socket specified, return "error: connection illegal for this process". If there is no room to create a new connection, return "error: insufficient resources".

LISTEN STATE
If active and the foreign socket is specified, then change the connection from passive to active, select an ISS. Send a SYN segment, set SND.UNA to ISS, SND.NXT to ISS+1. Enter SYN-SENT state. Data associated with SEND may be sent with SYN segment or queued for transmission after entering ESTABLISHED state. The urgent bit if requested in the command must be sent with the data segments sent as a result of this command. If there is no room to queue the request, respond with "error: insufficient resources". If Foreign socket was not specified, then return "error: foreign socket unspecified".

OPEN Call
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
Return "error: connection already exists".

[SEND Call
CLOSED STATE (i.e., TCB does not exist)
If the user does not have access to such a connection, then return "error: connection illegal for this process". Otherwise, return "error: connection does not exist".

LISTEN STATE
If the foreign socket is specified, then change the connection from passive to active, select an ISS. Send a SYN segment, set SND.UNA to ISS, SND.NXT to ISS+1. Enter SYN-SENT state. Data associated with SEND may be sent with SYN segment or queued for transmission after entering ESTABLISHED state. The urgent bit if requested in the command must be sent with the data segments sent as a result of this command. If there is no room to queue the request, respond with "error: insufficient resources". If Foreign socket was not specified, then return "error: foreign socket unspecified".

SYN-SENT STATE
SYN-RECEIVED STATE

Queue the data for transmission after entering ESTABLISHED state. If no space to queue, respond with "error: insufficient resources".

ESTABLISHED STATE
CLOSE-WAIT STATE
Segmentize the buffer and send it with a piggybacked acknowledgment (acknowledgment value = RCV.NXT). If there is insufficient space to remember this buffer, simply return "error: insufficient resources".

If the urgent flag is set, then SND.UP <- SND.NXT-1 and set the urgent pointer in the outgoing segments.

SEND Call
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
Return "error: connection closing" and do not service request.

RECEIVE Call
CLOSED STATE (i.e., TCB does not exist)

If the user does not have access to such a connection, return "error: connection illegal for this process". Otherwise return "error: connection does not exist".

LISTEN STATE
SYN-SENT STATE
SYN-RECEIVED STATE
Queue for processing after entering ESTABLISHED state. If there is no room to queue this request, respond with "error:  insufficient resources".

ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
If insufficient incoming segments are queued to satisfy the request, queue the request. If there is no queue space to remember the RECEIVE, respond with "error: insufficient resources".

Reassemble queued incoming segments into receive buffer and return to user. Mark "push seen" (PUSH) if this is the case. If RCV.UP is in advance of the data currently being passed to the user notify the user of the presence of urgent data.

When the TCP takes responsibility for delivering data to the user that fact must be communicated to the sender via an acknowledgment. The formation of such an acknowledgment is described below in the discussion of processing an incoming segment.

CLOSE-WAIT STATE
Since the remote side has already sent FIN, RECEIVEs must be satisfied by text already on hand, but not yet delivered to the user. If no text is awaiting delivery, the RECEIVE will get a "error: connection closing" response. Otherwise, any remaining text can be used to satisfy the RECEIVE.

CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
Return "error: connection closing".

CLOSE Call
CLOSED STATE (i.e., TCB does not exist)
If the user does not have access to such a connection, return "error: connection illegal for this process". Otherwise, return "error: connection does not exist".

LISTEN STATE
Any outstanding RECEIVEs are returned with "error: closing" responses. Delete TCB, enter CLOSED state, and return.

SYN-SENT STATE
Delete the TCB and return "error: closing" responses to any queued SENDs, or RECEIVEs.

SYN-RECEIVED STATE
If no SENDs have been issued and there is no pending data to send, then form a FIN segment and send it, and enter FIN-WAIT-1 state; otherwise queue for processing after entering ESTABLISHED state.

ESTABLISHED STATE
Queue this until all preceding SENDs have been segmentized, then form a FIN segment and send it. In any case, enter FIN-WAIT-1 state.

FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
Strictly speaking, this is an error and should receive a "error: connection closing" response. An "ok" response would be acceptable, too, as long as a second FIN is not emitted (the first FIN may be retransmitted though).

CLOSE Call
CLOSE-WAIT STATE
Queue this request until all preceding SENDs have been segmentized; then send a FIN segment, enter CLOSING state.

CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
Respond with "error: connection closing".

ABORT Call
CLOSED STATE (i.e., TCB does not exist)
If the user should not have access to such a connection, return "error: connection illegal for this process". Otherwise return "error: connection does not exist".

LISTEN STATE
Any outstanding RECEIVEs should be returned with "error: connection reset" responses. Delete TCB, enter CLOSED state, and return.

SYN-SENT STATE
All queued SENDs and RECEIVEs should be given "connection reset" notification, delete the TCB, enter CLOSED state, and return.

SYN-RECEIVED STATE
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
CLOSE-WAIT STATE

Send a reset segment:
<SEQ=SND.NXT><CTL=RST>
All queued SENDs and RECEIVEs should be given "connection reset" notification; all segments queued for transmission (except for the RST formed above) or retransmission should be flushed, delete the TCB, enter CLOSED state, and return.

CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
Respond with "ok" and delete the TCB, enter CLOSED state, and return.

STATUS Call
STATUS Call
CLOSED STATE (i.e., TCB does not exist)
If the user should not have access to such a connection, return "error: connection illegal for this process". Otherwise return "error: connection does not exist".

LISTEN STATE
Return "state = LISTEN", and the TCB pointer.

SYN-SENT STATE
Return "state = SYN-SENT", and the TCB pointer.

SYN-RECEIVED STATE
Return "state = SYN-RECEIVED", and the TCB pointer.

ESTABLISHED STATE
Return "state = ESTABLISHED", and the TCB pointer.

FIN-WAIT-1 STATE
Return "state = FIN-WAIT-1", and the TCB pointer.

FIN-WAIT-2 STATE
Return "state = FIN-WAIT-2", and the TCB pointer.

CLOSE-WAIT STATE
Return "state = CLOSE-WAIT", and the TCB pointer.

CLOSING STATE
Return "state = CLOSING", and the TCB pointer.

LAST-ACK STATE
Return "state = LAST-ACK", and the TCB pointer.

TIME-WAIT STATE
Return "state = TIME-WAIT", and the TCB pointer.

SEGMENT ARRIVES
SEGMENT ARRIVES
If the state is CLOSED (i.e., TCB does not exist) then all data in the incoming segment is discarded. An incoming segment containing a RST is discarded. An incoming segment not containing a RST causes a RST to be sent in response. The acknowledgment and sequence field values are selected to make the reset sequence acceptable to the TCP that sent the offending segment. If the ACK bit is off, sequence number zero is used,
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
If the ACK bit is on,
<SEQ=SEG.ACK><CTL=RST>
Return.

If the state is LISTEN then first check for an RST An incoming RST should be ignored. Return. second check for an ACK Any acknowledgment is bad if it arrives on a connection still in the LISTEN state. An acceptable reset segment should be formed for any arriving ACK-bearing segment. The RST should be formatted as follows:
<SEQ=SEG.ACK><CTL=RST>
Return.
third check for a SYN
If the SYN bit is set, check the security. If the security/compartment on the incoming segment does not exactly match the security/compartment in the TCB then send a reset and return.

<SEQ=SEG.ACK><CTL=RST>
If the SEG.PRC is greater than the TCB.PRC then if allowed by the user and the system set TCB.PRC<-SEG.PRC, if not allowed send a reset and return.


<SEQ=SEG.ACK><CTL=RST>
If the SEG.PRC is less than the TCB.PRC then continue. Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other control or text should be queued for processing later. ISS should be selected and a SYN segment sent of the form:
<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
SND.NXT is set to ISS+1 and SND.UNA to ISS. The connection state should be changed to SYN-RECEIVED. Note that any other incoming control or data (combined with SYN) will be processed in the SYN-RECEIVED state, but processing of SYN and ACK should not be repeated. If the listen was not fully specified (i.e., the foreign socket was not fully specified), then the unspecified fields should be filled in now. fourth other text or control

Any other control or text-bearing segment (not containing SYN) must have an ACK and thus would be discarded by the ACK processing. An incoming RST segment could not be valid, since it could not have been sent in response to anything sent by this incarnation of the connection. So you are unlikely to get here, but if you do, drop the segment, and return.

If the state is SYN-SENT then first check the ACK bit
If the ACK bit is set
If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless the RST bit is set, if so drop the segment and return)
<SEQ=SEG.ACK><CTL=RST>
and discard the segment. Return.
If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable.

second check the RST bit

SEGMENT ARRIVES
If the RST bit is set If the ACK was acceptable then signal the user "error:
connection reset", drop the segment, enter CLOSED state, delete TCB, and return. Otherwise (no ACK) drop the segment and return.
third check the security and precedence
If the security/compartment in the segment does not exactly match the security/compartment in the TCB, send a reset If there is an ACK
<SEQ=SEG.ACK><CTL=RST>
Otherwise
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
If there is an ACK

The precedence in the segment must match the precedence in the TCB, if not, send a reset
<SEQ=SEG.ACK><CTL=RST>
If there is no ACK
If the precedence in the segment is higher than the precedence in the TCB then if allowed by the user and the system raise the precedence in the TCB to that in the segment, if not allowed to raise the prec then send a reset.
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
If the precedence in the segment is lower than the precedence in the TCB continue.
If a reset was sent, discard the segment and return.

fourth check the SYN bit

This step should be reached only if the ACK is ok, or there is no ACK, and it the segment did not contain a RST.
If the SYN bit is on and the security/compartment and precedence are acceptable then, RCV.NXT is set to SEG.SEQ+1, IRS is set to
SEG.SEQ. SND.UNA should be advanced to equal SEG.ACK (if there is an ACK), and any segments on the retransmission queue which are thereby acknowledged should be removed.

If SND.UNA > ISS (our SYN has been ACKed), change the connection state to ESTABLISHED, form an ACK segment
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
and send it. Data or controls which were queued for transmission may be included. If there are other controls or text in the segment then continue processing at the sixth step below where the URG bit is checked, otherwise return.

Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
and send it. If there are other controls or text in the segment, queue them for processing after the ESTABLISHED state has been reached, return.

fifth, if neither of the SYN or RST bits is set then drop the segment and return.

SEGMENT ARRIVES
Otherwise, first check sequence number
SYN-RECEIVED STATE
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
Segments are processed in sequence. Initial tests on arrival are used to discard old duplicates, but further processing is done in SEG.SEQ order. If a segment’s contents straddle the boundary between old and new, only the new parts should be processed.
There are four cases for the acceptability test for an incoming segment:

Segment Receive Test

LengthWindow 00SEG.SEQ = RCV.NXT0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND>00not acceptable>0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WNDIf the RCV.WND is zero, no segments will be acceptable, but special allowance should be made to accept valid ACKs, URGs and RSTs.

If an incoming segment is not acceptable, an acknowledgment should be sent in reply (unless the RST bit is set, if so drop the segment and return):
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

After sending the acknowledgment, drop the unacceptable segment and return.

In the following it is assumed that the segment is the idealized segment that begins at RCV.NXT and does not exceed the window.

One could tailor actual segments to fit this assumption by trimming off any portions that lie outside the window (including SYN and FIN), and only processing further if the segment then begins at RCV.NXT. Segments with higher begining sequence numbers may be held for later processing.

second check the RST bit,
SYN-RECEIVED STATE
If the RST bit is set
If this connection was initiated with a passive OPEN (i.e., came from the LISTEN state), then return this connection to LISTEN state and return. The user need not be informed. If this connection was initiated with an active OPEN (i.e., came from SYN-SENT state) then the connection was refused, signal the user "connection refused". In either case, all segments on the retransmission queue should be removed. And in the active OPEN case, enter the CLOSED state and delete the TCB, and return.

ESTABLISHED
FIN-WAIT-1
FIN-WAIT-2
CLOSE-WAIT
If the RST bit is set then, any outstanding RECEIVEs and SEND should receive "reset" responses. All segment queues should be flushed. Users should also receive an unsolicited general "connection reset" signal. Enter the CLOSED state, delete the TCB, and return.

CLOSING STATE
LAST-ACK STATE
TIME-WAIT
If the RST bit is set then, enter the CLOSED state, delete the TCB, and return.

SEGMENT ARRIVES
third check security and precedence

SYN-RECEIVED
If the security/compartment and precedence in the segment do not exactly match the security/compartment and precedence in the TCB then send a reset, and return.

ESTABLISHED STATE
If the security/compartment and precedence in the segment do not exactly match the security/compartment and precedence in the TCB then send a reset, any outstanding RECEIVEs and SEND should receive "reset" responses. All segment queues should be flushed. Users should also receive an unsolicited general "connection reset" signal. Enter the CLOSED state, delete the TCB, and return.

Note this check is placed following the sequence check to prevent a segment from an old connection between these ports with a different security or precedence from causing an abort of the current connection.

fourth, check the SYN bit,
SYN-RECEIVED
ESTABLISHED STATE
FIN-WAIT STATE-1
FIN-WAIT STATE-2
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
If the SYN is in the window it is an error, send a reset, any outstanding RECEIVEs and SEND should receive "reset" responses, all segment queues should be flushed, the user should also receive an unsolicited general "connection reset" signal, enter the CLOSED state, delete the TCB, and return.

If the SYN is not in the window this step would not be reached and an ack would have been sent in the first step (sequence number check).

fifth check the ACK field,
if the ACK bit is off drop the segment and return
if the ACK bit is on
SYN-RECEIVED STATE
If SND.UNA =< SEG.ACK =< SND.NXT then enter ESTABLISHED state and continue processing.
If the segment acknowledgment is not acceptable, form a reset segment,
<SEQ=SEG.ACK><CTL=RST>
and send it.

ESTABLISHED STATE
If SND.UNA < SEG.ACK =< SND.NXT then, set SND.UNA <- SEG.ACK.

Any segments on the retransmission queue which are thereby entirely acknowledged are removed. Users should receive positive acknowledgments for buffers which have been SENT and fully acknowledged (i.e., SEND buffer should be returned with "ok" response). If the ACK is a duplicate (SEG.ACK < SND.UNA), it can be ignored. If the ACK acks something not yet sent (SEG.ACK > SND.NXT) then send an ACK, drop the segment, and return.

If SND.UNA < SEG.ACK =< SND.NXT, the send window should be updated. If (SND.WL1 < SEG.SEQ or (SND.WL1 = SEG.SEQ and SND.WL2 =< SEG.ACK)), set SND.WND <- SEG.WND, set SND.WL1 <- SEG.SEQ, and set SND.WL2 <- SEG.ACK. Note that SND.WND is an offset from SND.UNA, that SND.WL1 records the sequence number of the last segment used to update SND.WND, and that SND.WL2 records the acknowledgment number of the last segment used to update SND.WND. The check here prevents using old segments to update the window.

SEGMENT ARRIVES
FIN-WAIT-1 STATE
In addition to the processing for the ESTABLISHED state, if our FIN is now acknowledged then enter FIN-WAIT-2 and continue processing in that state.

FIN-WAIT-2 STATE
In addition to the processing for the ESTABLISHED state, if the retransmission queue is empty, the user’s CLOSE can be acknowledged ("ok") but do not delete the TCB.

CLOSE-WAIT STATE
Do the same processing as for the ESTABLISHED state.

CLOSING STATE
In addition to the processing for the ESTABLISHED state, if the ACK acknowledges our FIN then enter the TIME-WAIT state, otherwise ignore the segment.

LAST-ACK STATE
The only thing that can arrive in this state is an acknowledgment of our FIN. If our FIN is now acknowledged, delete the TCB, enter the CLOSED state, and return.

TIME-WAIT STATE
The only thing that can arrive in this state is a retransmission of the remote FIN. Acknowledge it, and restart the 2 MSL timeout.

sixth, check the URG bit,
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
If the URG bit is set, RCV.UP <- max(RCV.UP,SEG.UP), and signal the user that the remote side has urgent data if the urgent pointer (RCV.UP) is in advance of the data consumed. If the user has already been signaled (or is still in the "urgent mode") for this continuous sequence of urgent data, do not signal the user again.

CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT
This should not occur, since a FIN has been received from the remote side. Ignore the URG.

seventh, process the segment text,
ESTABLISHED STATE
FIN-WAIT-1 STATE
FIN-WAIT-2 STATE
Once in the ESTABLISHED state, it is possible to deliver segment text to user RECEIVE buffers. Text from segments can be moved into buffers until either the buffer is full or the segment is empty. If the segment empties and carries an PUSH flag, then the user is informed, when the buffer is returned, that a PUSH has been received.

When the TCP takes responsibility for delivering the data to the user it must also acknowledge the receipt of the data.

Once the TCP takes responsibility for the data it advances RCV.NXT over the data accepted, and adjusts RCV.WND as apporopriate to the current buffer availability. The total of RCV.NXT and RCV.WND should not be reduced.

Send an acknowledgment of the form:
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
This acknowledgment should be piggybacked on a segment being transmitted if possible without incurring undue delay.

SEGMENT ARRIVES
CLOSE-WAIT STATE
CLOSING STATE
LAST-ACK STATE
TIME-WAIT STATE
This should not occur, since a FIN has been received from the remote side. Ignore the segment text.

eighth, check the FIN bit, Do not process the FIN if the state is CLOSED, LISTEN or SYN-SENT since the SEG.SEQ cannot be validated; drop the segment and return.

If the FIN bit is set, signal the user "connection closing" and return any pending RECEIVEs with same message, advance RCV.NXT over the FIN, and send an acknowledgment for the FIN. Note that FIN implies PUSH for any segment text not yet delivered to the user.

SYN-RECEIVED STATE
ESTABLISHED STATE
Enter the CLOSE-WAIT state.
FIN-WAIT-1 STATE
If our FIN has been ACKed (perhaps in this segment), then enter TIME-WAIT, start the time-wait timer, turn off the other timers; otherwise enter the CLOSING state.

FIN-WAIT-2 STATE
Enter the TIME-WAIT state. Start the time-wait timer, turn off the other timers.

CLOSE-WAIT STATE
Remain in the CLOSE-WAIT state.

CLOSING STATE
Remain in the CLOSING state.

LAST-ACK STATE
Remain in the LAST-ACK state.

TIME-WAIT STATE
Remain in the TIME-WAIT state. Restart the 2 MSL time-wait timeout. and return.

USER TIMEOUT
USER TIMEOUT
For any state if the user timeout expires, flush all queues, signal the user "error: connection aborted due to user timeout" in general and for any outstanding calls, delete the TCB, enter the CLOSED state and return.

RETRANSMISSION TIMEOUT
For any state if the retransmission timeout expires on a segment in the retransmission queue, send the segment at the front of the retransmission queue again, reinitialize the retransmission timer, and return.

TIME-WAIT TIMEOUT
If the time-wait timeout expires on a connection delete the TCB, enter the CLOSED state and return.


0 0
原创粉丝点击