- 论坛徽章:
- 0
|
作者:dlmu2001
RFC793中文翻译三
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP Header Format
Note that one tick mark represents one bit position.
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 | \ -----------
+---------+| |
| SYN | rcv SYN | SYN |
| RCVD || 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的时候,算法保留系列号的关系。计算模算法有些微妙,必须在比较这些值的编程的时候谨慎考虑。符号“=0 RCV.NXT =0 0 not acceptable
>0 >0 RCV.NXT = --> SYN-RECEIVED
3. 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-RECEIVED
5. SYN-RECEIVED --> ...
6. ESTABLISHED --> 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 --> LISTEN
6. ... --> SYN-RECEIVED
7. SYN-SENT --> 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. (!!) --> (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. (??) --> (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. (??) --> (return to LISTEN!)
5. LISTEN LISTEN
Old Duplicate SYN Initiates a Reset on two Passive Sockets
Figure 12.
各种各样的情况都有可能,所有的这些情况遵循RST产生和处理的规则。
Rest产生
作为一条基本规则,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状态。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15315/showart_205020.html |
|