3
头图

《网络是怎么连接的》的第二章介绍了操作系统中的协议栈和网卡是如何将应用程序的消息发给服务器的:

  1. 解创建套接字
  2. 连接服务器
  3. 收发数据
  4. 从服务器断开连接并删除套接字
  5. IP与以太网的包收发操作
  6. 用UDP收发数据的操作

其中涉及到很多的概念:TCP IP 以太网 UDP

本文基于rfc793 及其后续修订版,摘录其中部分内容,试着找一找工作中的使用场景。

TCP

黑体字见附录

0.附录(基本在百度百科上搜的)

  1. 主机到主机 host-to-host:对应OSI七层模型的传输层。
  2. 分组交换 packet switching:通信双方以分组为单位、使用存储-转发机制实现数据交互的通信方式。也称包交换,将用户通信的数据划分成多个更小的等长数据段。
    例如:TCP的存储-转发,TCP有一个收发缓冲区,将数据组装成网络包发送。
  3. 鲁棒性 robust:健壮和强壮的意思,在异常和危险情况下系统不奔溃、不死机的能力。
  4. 拥塞 congestion:拥塞是指到达通信子网中分组数量过多来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿。类比交通阻塞。
  5. 面向连接:connection-oriented,具备以下特征:建立一条虚电路(比如3次握手),排序(序号),确认(ACK),流量控制。
  6. 端到端:end-to-end,端到端是网络连接。网络要通信,无论中间有多少机器,只要在两头(源和目的)建立连接即端对端连接。
  7. 分层结构:上层调用下层,下层对上层一无所知。例如网络七层模型
  8. 多网络:也称多重网络,使用多种通信媒体的网络群组。
  9. 通信媒体:也称传输媒介,可分为有线(光纤,双绞线,同轴电缆)和无线
  10. 硬线连接:??查不到资料
  11. 电路交换:主要应用于电话通信。
  12. 基于时钟:clock-based,时钟即cpu时钟,是CPU自带的时钟。CPU时钟周期,通常为节拍脉冲或T周期,它是处理操作的最基本的单位。右击我的电脑 --> 属性,可以看到电脑的GHz。
  13. 以太网:ETHERNET,是目前最常用的计算机局域网技术。
  14. 包交换器:应用了通信技术,对分组的数据信息进行程序处理的通信设备。
  15. 驱动程序:是一种可以使计算机和设备进行相互通信的特殊程序。相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作。

1.简介

高可靠、主机到主机协议,用于分组交换计算机通信网络。
本文介绍程序实现TCP,用户和程序调用TCP服务接口时,TCP协议提供哪些功能。

1.1 目的

为解决军事通信网络的可靠性和可用性而生,同时适用于政府和民间网络通信。
关注计算机通信系统不可靠时的鲁棒性拥塞时的可用性。

TCP面向连接端到端的高可靠协议。适用于分层结构协议且支持多网络应用程序。TCP假设下层协议是不可靠的。原则上适用范围从硬线连接到分组交换或电路交换网络

                       Protocol Layering

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

1.2 范围

用于多网络环境下进程间可靠通信服务。

1.3 关于文档

描述了 TCP服务之间,以及TCP与高层次协议交互的规范。
剩余章节简洁了协议的接口和操作
章节二:总结了TCP设计的基本原理
章节三:提供了TCP在各种事件发生时(新段的到达、用户调用、错误等)所需要的动作的详细描述,以及TCP段格式的详细信息。

1.4 接口

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

应用程序和TCP间的接口将详细阐述。接口包含一套调用集合。例如打开关闭连接,建立在连接上的收发数据。应用程序和TCP之间是异步通信。

TCP协议设计出来工作于通用的互联网环境上,本文假设底层协议是IP

1.5 操作

如上所述,TCP的主要目的是进程对之间提供可靠、安全的逻辑电路和连接服务。

为了在不太可靠的互联网通讯系统上提供如上服务,需要以下设施。

  • 基本的数据传输
  • 可靠能力
  • 流量控制
  • 多路复用
  • 连接
  • 优先级和安全
1.5.1 基本的传输能力

TCP按一定的字节长度打包成,能够双向传输连续的八位(octets)字节流。
通常由TCPs决定何时阻塞或推送数据。
TCP定义了一个push功能,可以立即推送数据。

1.5.2 可靠性

目的:当数据被网络通信系统损坏、丢失、复制或无序的传输时,TCP必须进行数据恢复。
方案
丢失:发送方为每个字节分配序列号,接收方返回确认(ACK)。超时时间内接收方没有收到ACK,数据将被重传。
有序和去重:在接收端,使用序列号正确地排列,并去重。
损坏:给每个传输的段添加一个校验和,在接收端做校验并丢弃损坏的段。

TCP可以从网络通信系统的错误中恢复。

1.5.3 流量控制

如果发送速率过快来不及接收可能会丢包,重发,网络拥塞。
TCP通过“窗口”机制给接收方提供一种控制发送方流量速率的方法。

  1. 接收方收到数据并将数据交给应用程序之后,返回窗口给发送方。
  2. 发送方通过窗口大小来调整发送速率。

窗口即当前接收缓冲区的大小。

1.5.4 多路复用
  1. 允许单个主机的多个进程使用TCP设施
  2. 一个套接字给多个连接使用

TCP端口和来自网络层的ip地址组成套接字,一对套接字标识一个连接。一个套接字复用于多个连接。

不难发现,多路复用的关键是套接字
套接字:IP地址+端口号
1.5.5 连接

可靠性和流控制机制要求TCPs为每个数据流初始化和维护某些状态信息。
这些状态信息包括套接字、序列号和窗口大小,被称为一个连接。
连接由两端的一对套接字唯一标识。

当两个进程想要通信时,它们的TCPs必须首先建立一个连接(初始化两边的状态信息),通信完成时,连接被终止或关闭。

由于连接建立在不可靠的主机之间和不可靠的internet通信系统上,为了避免连接的错误初始化,使用了一套基于时钟的序列号的握手机制。

1.5.6 优先级和安全性

用户可以指定通信的安全性和优先级。

2. 基本原理(PHILOSOPHY)

2.1 互联网络系统的组成部分

互联网络环境由连在网络上的主机以及通过网关互联的网络组成。
进程间通信系统需要主机、网络、网关上各级协议的支持,并在进程端口间的逻辑连接(例如:TCP)上提供双向的数据流。
每个进程都可以有几个端口,进程通过端口区分彼此以及互相通信。

  1. 进程:被视为主机的中活动的元素。
  2. 进程间通信:如果终端、文件、I/O设备通过进程进行彼此通信,也视为进程间通信。
  3. 主机:连接到网络的计算机,从通信网络的角度看,主机是数据包的源和目的地
  4. 网络:可以是本地网络(例如:以太网)或大型网络(例如:CSTNET),都是基于分组转换技术。
  5. 包:是TCP/IP协议通信传输中的数据单位,一般也称“数据包”。TCP不关心上层的数据结构。
  6. 逻辑连接:例如TCP连接。物理连接,例如网线连接。

2.2 运行方式

  +------------------------------------+
  |            higher-level            |
  +------------------------------------+
  |              TCP module            |
  +------------------------------------+
  |      internet protocol module      |
  +------------------------------------+
  |        network device driver       |
  +------------------------------------+
  |        communication network       |
  +------------------------------------+

TCP module -- TCP通信模型:

  1. 进程使用缓冲区作为参数,将数据传递给TCP模块。
  2. TCP模块将缓存中的数据打包成,调用 ip module 传输数据给目标TCP。
  3. 接收方TCP将数据从段中取出放入接受方缓冲区并通知接收方用户。TCP段中的控制信息(TCP头)用于确保数据有序可靠的传输。

internet protocol module -- IP通信模型:

  1. TCP调用ip模块
  2. ip模块将段封装成internet数据报,ip头部包含了目的ip模块或中间网关的路由信息。
  3. ip模块将internet数据报封装到局域网包中,例如MAC。调用网卡驱动发送数据。
  4. 包交换可以执行进一步的包装,分片或者其它操作以投递局域网到目的ip module
  5. 网关从它的局域网包中取出IP数据报,检查并确定下一步路由。然后将IP数据报封装到在适合于下一个网络的局域网包中,路由到下一个网关,或最终目的地
  6. 目的地ip模块将IP数据报展开成段,并将其传递给目的地TCP。

包交换器:应用了通信技术,对分组的数据信息进行程序处理的通信设备
局域网:局域网是一种私有网络,一般在一座建筑物内或建筑物附近,比如家庭、办公室或工厂。
展开:将IP数据报重组成段

2.3 主机环境

假设操作系统中有个TCP模块。用户访问TCP就像访问文件系统一样。TCP模块可能调用其他的操作系统功能。假设网络的实际接口由设备驱动模块控制。TCP调用ip模块,该模块调用网络设备驱动程序

TCP机制不排斥前端处理器实现。主机到前端协议必须支持本文描述的TCP/user接口的功能,见2.4

前端处理器:front end processor,FEP。也称通信控制器。例如:LVS 路由器 多路复用器。

2.4 接口

TCP接口分两类:
TCP/user:提供给用户或者应用程序使用
TCP/internet:TCP模块提供给底层协议(如IP协议)使用

TCP/user:打开/关闭连接,发送/接受数据,获取连接状态等功能。
TCP/internet:提供了从远端(因特网上任意主机的TCP模块)发送和接收数据报的功能。具有如下参数:传递地址、服务类型、优先级、安全性和其他控制信息。

2.5 与其他协议的关系

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

                     Protocol Relationships

                           Figure 2.

2.6 通信的可靠性

在TCP连接上发送的数据流到达目的地后是有序,可靠的。

通过序列号和确认使传输变得可靠。数据每8bit(octet)分配一个序号。TCP头部携带的序列号等于段中前8bit分配的序列号。确认号等于发送方期望下一次收到的序列号。TCP传输一个包含数据的段时,将副本放入重传队列并启动一个计时器;收到确认号后删除副本。计时器结束前没收到重传。

    TCP A                                          TCP B
1.  ESTABLISHED --> <SEQ=100><DATA size=1460>  --> ESTABLISHED
2.  ESTABLISHED <-- <ACK=1561><CTL=ACK><DATA>  <-- ESTABLISHED
3.  ESTABLISHED --> <SEQ=1561><DATA size=1460> --> ESTABLISHED

http://c.biancheng.net/view/2352.html

TCP确认并不保证数据已经交付给用户了。以bio为例:

+------------------------+
|用户空间  用户空间缓冲区  |
+------------------------+
|内核空间  套接字缓冲区    |
+------------------------+
|          network       |
+------------------------+
如上图,数据到达接收方TCP,TCP检查收到的数据块和TCP头部内容,判断数据是否有丢失,没有问题返回确认。然后将数据暂存到套接字缓冲区,并将数据按顺序连接还原出原始数据,最后将数据交给应用程序。

//TODO nio是对上述流程带来的影响?

为了控制TCPs之间的数据流量,采用了一个流量控制机制。接收方TCP会向发送方TCP报告一个“窗口”。窗口代表接收方能接收的字节大小。

2.7. 连接建立和清除

问:如何标识独立的数据流?
答:套接字是网络上是唯一标识,由ip地址和tcp提供的端口组成。连接由两端的一对套接字组成(本地ip 本地port 外部ip 外部port)。一条连接可以双向传输,称为“全双工”。TCPs可以选择任意的port和进程进行关联。

在任何实现中有些必须的基本概念:
套接字:连接端口号和程序。程序可以拥有端口号,并在端口上启动连接。
连接:由调用OPEN时传入的参数(本地端口,外部套接字)决定。TCP会返回一个本地连接名称,用户通过它在随后的调用中引用连接。一种实现策略,将本地连接名称设置为指向TCB的指针。
TCB:Transmission Control Block,用于存储连接的控制信息。
OPEN:OPEN调用会指定连接建立是主动进行,还是被动等待。

passive OPEN:如果进程希望为其他进程提供服务,可以使用passive OPEN请求,外部地址使用0.0.0.0:0表示套接字尚未被指定。未指定的套接字只允许出现于passive OPEN。对应的连接状态为Listener

对于 local passive OPENs 和 foreign active OPENs 的匹配规则主要有两种情况。第一,local passive OPENs 指定了外部套接字时需精准匹配。第二,local passive OPENs 没指定外部套接字,任意外部套接字都能接受。其它可能的情况包括部分严格匹配。

foreign socket: 0.0.0.0:0
0表示任意,不做限制。
如果不为0,需要精确匹配。

建立连接的过程使用同步(SYN)控制标志,涉及“三次握手”。当序列号在两个方向上同步完成,连接就建立了。连接的清除涉及段的交换,段会携带带有FIN的控制标志。

2.8 数据通信

连接上的数据流是8bit流。发送用户在调用SEND函数可以通过标志位PUH立即发送数据。

发送方TCP允许从用户处先收集数据等到方便时再封装到段里发送,收到push函数,必须发送所有未发送数据。当接收方TCP看到PSH标志,马上将数据转交给接收进程。

TCP定义了紧急数据。TCP没有规定收到紧急数据应该做什么,一般情况下,接收进程应该尽快处理紧急数据。

2.9 安全和优先级

TCP利用internet协议的服务字段和安全选项,为TCP用户提供基于每个连接的优先级和安全性。
当TCP工作于多级安全环境下,需要提供安全和优先级的选项。大部分TCP的实现是多级安全环境的一个子集。
在多级安全环境中运行的TCP模块必须正确标记出安全段、分隔段和优先级。还必须向其用户或更高级别的协议(如Telnet或THP)提供接口,用于指定安全级别、间隔和连接的优先级。

2.10 鲁棒性原则

TCP实现将遵循健壮性的一般原则: 自己做的事情上要谨慎,从别人那里接受的事情上要自由(容错)。
be conservative in what you do, be liberal in what you accept from others.

3. 功能规格

3.1 头部格式

TCP段作为internet数据报发送。IP报头包含几个消息头(源主机地址和目标主机地址)。TCP报头跟在internet报头后面。

    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                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Sequence Number: 序列号 32 bits

这个段的第一个数据字节的序列号(出现*SYN控制位*时除外)。 如果存在SYN,序列号代表初始序列号(ISN),第一个数据字节是ISN+1。  

Acknowledgment Number: 确认号 32 bits

如果设置了*ACK控制位*,确认号=接收方期待的下一个收到的序列号。

Data Offset: 数据偏移量 4 bits

标识数据从哪里开始

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

URG:  紧急标识
ACK:  确认标识
PSH:  立即发送
RST:  重置连接
SYN:  同步序列号
FIN:  没有更多的数据需要发送了

Window: 窗口 16 bits

携带窗口的段的发送方愿意接受的数据字节数

Checksum: 校验和 16 bits

16字节 = 伪首部12字节,校验和4字节

首先是伪首部:源地址,目标地址,预留空间,传输层协议号(TCP是6)、TCP报文长度(报头+数据)
                     +--------+--------+--------+--------+
                     |           Source Address          |
                     +--------+--------+--------+--------+
                     |         Destination Address       |
                     +--------+--------+--------+--------+
                     |  zero  |  PTCL  |    TCP Length   |
                     +--------+--------+--------+--------+
最后计算校验和,校验和计算方式:将TCP段以16bit为单位相加,然后取反码。

Urgent Pointer: 紧急指针 16 bits

紧急指针指向紧急数据在报文段中结束的位置

Options: 可选项 变长 //TODO 暂为793规定的可选项

数据结构:
| kind(1字节) | length(1字节) | info(n字节) |

      Kind     Length    Meaning
      ----     ------    -------
       0         -       End of option list.
       1         -       No-Operation
       2         4       最大分段大小.

      End of Option List

        +--------+
        |00000000|
        +--------+
         Kind=0
表示可选项列表结束

      No-Operation

        +--------+
        |00000001|
        +--------+
         Kind=1
在可选项之间使用,占一字节,用于选项间填充数据,做对齐。

      MSS:最大分段大小
      +--------+--------+---------+--------+
      |00000010|00000100|   max seg size   |
      +--------+--------+---------+--------+
      Kind=2   Length=4
最大分段大小,只在连接初始化时使用。接收方用它来告诉发送者,我期望的最大分段大小是多少。

Padding: 填充 变长

确保TCP头部长度为32bit的整数倍。

3.2 术语

讨论TCP操作之前,需要详细的介绍一些术语。这些术语大致分为2部分:

  1. TCB:Transmission Control Block 传输控制块
  2. 当前段(segment)相关变量
  3. 连接的生命周期中经历的一系列状态
3.2.1 TCB

维护TCP连接需要记录一些变量,这些变量被存储在TCB中。
存储在TCB中的变量包括:

  1. 本地和远程套接字编号
  2. 连接的安全性和优先级
  3. 指向用户发送和接收缓冲区的指针
  4. 指向重传队列和指向当前段的指针
  5. 与发送和接收序列号相关的几个变量

发送序列号相关的变量

SND.UNA - 已发送 未经确认
SND.NXT - 发送方 下一个要发送的序列号
SND.WND - 发送窗口
SND.UP -  发送紧急指针
SND.WL1 - 上次窗口更新的时段系列号(segment sequence number used for last window update)。发送方收到接收方返回的窗口,触发窗口更新时会保存一个段序列号
SND.WL2 - 用于上次窗口更新的段确认号(segment acknowledgment number used for last Window update)。发送方收到接收方返回的窗口,触发窗口更新时会保存一个段确认号
ISS - 初始发送系列号,三次握手阶段使用

  发送序列空间,发送窗口即图4第三部分

                   1         2          3          4
              ----------|----------|----------|----------
                     SND.UNA    SND.NXT    SND.UNA
                                          +SND.WND

        1 - 已传输数据已收到确认的旧序列号
        2 - 已传输数据未收到确认数据的序列号
        3 - 当前允许用于传输数据但还未传输的序列号
        4 - 当前不允许传输的将来的系列号

                               Figure 4.

接收序列号相关的变量

      RCV.NXT - 接收下一个
      RCV.WND - 接收窗口
      RCV.UP  - 接收紧急指针
      IRS     - 初始化接收序列号

  接收序列空间, 接收窗口即图5第2部分。

                       1          2          3
                   ----------|----------|----------
                          RCV.NXT    RCV.NXT
                                    +RCV.WND

        1 - 已确认的旧序列号
        2 - 允许接收的新序列号
        3 - 不允许接收的未来序列号
        
                               Figure 5.
    
3.2.2 当前段(segment)相关变量

讨论中还经常使用一些变量,它们的值来自当前段的变量。

当前段变量

      SEG.SEQ - 段序列号
      SEG.ACK - 段确认号
      SEG.LEN - 段长度
      SEG.WND - 段窗口
      SEG.UP  - 段紧急指针
      SEG.PRC - 段优先级字段
3.2.3 连接的生命周期中经历的一系列状态

一个连接在其生命周期中会经历一系列的状态:

建立连接
LISTEN、SYN-SENT、SYN-RECEIVED、
连接中
ESTABLISHED
断开连接
FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT
不在连接状态
CLOSED

CLOSED是虚构的,表示没有任何连接状态,TCB不存在。

状态机


                              +---------+ ---------\      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 序列号

设计TCP时有个基础概念:TCP连接上每8bit数据都会分配一个序列号。
由于数据流每八位分配一个序号,所以没有序号都可以用来确认,确认号X代表X之前的序号都已确认,但不包括X。这种机制可用于重传。紧跟在头后面的第一个8bit是最低序号,接下来的8bit是连续序号。

序号是int型,取值范围 0 ~ 2^32-1(4,294,967,296) == 4G. 对于溢出的数值,计算机做取模操作。

几种典型的TCP必须处理的序列号比较:

(a) 确认(acknowledgements)指向的序列号已发送但未确认
(b) 段中的序列号已确认,从重传队列中移除段
(c) 接收到的段中包含符合预期的序列号(是否在接收窗口范围内)。

作为发送数据响应,TCP收到确认(acknowledgements)时,会进行以下比较:

SND.UNA = 最大未确认的序列号
SND.NXT = 下一个要发送的序列号
SEG.ACK = 接收方TCP发送过来的确认 (接收TCP所期望的下一个序列号)
SEG.SEQ = 段的第一个序列号
SEG.LEN = 段中数据占用的字节数(包括SYN和FIN)
SEG.SEQ+SEG.LEN-1 = 段的最后序列号

一个新的确认号,遵循下方的不等式:
SND.UNA < SEG.ACK =< SND.NXT
如果重传队列上的段的序列号和长度之和小于或等于传入段中的确认值,则该段被完全确认

当接收数据时需要做以下比较:

RCV.NXT = 预期接收到的下一个段的序列号,在接收窗口的左边缘  RCV.NXT+RCV.WND-1 = 预期接收段的最后一个段,再接收窗口的右边缘
SEG.SEQ = 接收段的占用的第一个序列号
SEG.SEQ+SEG.LEN-1 = 接收段占用的最后一个序列号

检查段序列号的合法性性,需满足以下两个条件:
1. RCV.NXT =<SEG.SEQ<RCV.NXT+RCV.WND
2. RCV.NXT=<SEG.SEQ+SEG.LEN-1<RCV.NXT+RCV.WND

实际情况需要考虑,零窗口和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字段。

3.3.1 ISN(初始序列号)

// TODO 为什么ISN是一个随机数以及它的随机算法?

发送的每个段会占用序列空间中的一个多个序列号,被段占用的号码都是“busy”或“in use”状态直到经过MSL秒(maximun segment lifetime)。

3.3.2 TCP静止时间概念

3.4 建立连接

  TCP A                                                TCP B
1.  CLOSED                                               LISTEN
2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED
3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED
4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>       --> ESTABLISHED
5.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED

                      三次握手
                    Figure 7.

  TCP A                                            TCP B
1.  CLOSED                                           CLOSED
2.  SYN-SENT     --> <SEQ=100><CTL=SYN>              ...
3.  SYN-RECEIVED <-- <SEQ=300><CTL=SYN>              <-- SYN-SENT
4.               ... <SEQ=100><CTL=SYN>              --> SYN-RECEIVED
5.  SYN-RECEIVED --> <SEQ=100><ACK=301><CTL=SYN,ACK> ...
6.  ESTABLISHED  <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
7.               ... <SEQ=101><ACK=301><CTL=ACK>     --> ESTABLISHED

                    同时发起连接
                      Figure 8.
  TCP A                                                TCP B
1.  CLOSED                                               LISTEN
2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               ...
3.  (duplicate) ... <SEQ=90><CTL=SYN>               --> SYN-RECEIVED
4.  SYN-SENT    <-- <SEQ=300><ACK=91><CTL=SYN,ACK>  <-- SYN-RECEIVED
5.  SYN-SENT    --> <SEQ=91><CTL=RST>               --> LISTEN
6.              ... <SEQ=100><CTL=SYN>               --> SYN-RECEIVED
7.  SYN-SENT    <-- <SEQ=400><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED
8.  ESTABLISHED --> <SEQ=101><ACK=401><CTL=ACK>      --> ESTABLISHED
                    Recovery from Old Duplicate SYN
                               Figure 9.
  TCP A                                           TCP B
1.  (CRASH)                               (send 300,receive 100)
2.  CLOSED                                           ESTABLISHED
3.  SYN-SENT --> <SEQ=400><CTL=SYN>              --> (??)
4.  (!!)     <-- <SEQ=300><ACK=100><CTL=ACK>     <-- ESTABLISHED
5.  SYN-SENT --> <SEQ=100><CTL=RST>              --> (Abort!!)
6.  SYN-SENT                                         CLOSED
7.  SYN-SENT --> <SEQ=400><CTL=SYN>              -->
                     半连接
                     Figure 10.

// TODO 半连接与RST


wzyAcyy
9 声望2 粉丝