跳到主要内容

附录E. 事件处理

附录E: 事件处理 (Event Processing)

事件处理 (Event Processing)

OPEN调用 (OPEN Call)

...
选择初始发送序列号 (ISS)。发送以下形式的SYN段:

<SEQ=ISS><CTL=SYN><TSval=my.TSclock><WSopt=Rcv.Wind.Scale>

...

SEND调用 (SEND Call)

CLOSED状态 (即TCB不存在)

...

LISTEN状态

如果指定了外部套接字,则将连接从被动更改为主动,选择ISS。
发送包含以下选项的SYN段:<TSval=my.TSclock>和<WSopt=Rcv.Wind.Scale>。
将SND.UNA设置为ISS,SND.NXT设置为ISS+1。进入SYN-SENT状态。...

SYN-SENT状态
SYN-RECEIVED状态

...

ESTABLISHED状态
CLOSE-WAIT状态

分段缓冲区并使用捎带确认 (acknowledgment value = RCV.NXT) 发送它。...

如果设置了紧急标志...

如果设置了Snd.TS.OK标志,则在每个数据段中包含TCP时间戳选项
<TSval=my.TSclock,TSecr=TS.Recent>。

缩放接收窗口以在段头中传输:

SEG.WND = (SND.WND >> Rcv.Wind.Scale).

段到达 (SEGMENT ARRIVES)

...

如果状态是LISTEN,则

首先检查RST

...

其次检查ACK

...

第三检查SYN

如果设置了SYN位,检查安全性。如果...

...

如果SEG.PRC小于TCB.PRC,则继续。

检查窗口缩放选项 (WSopt);如果找到,将SEG.WSopt保存在Snd.Wind.Scale中
并设置Snd.WS.OK标志。否则,将Snd.Wind.Scale和Rcv.Wind.Scale都设置为零
并清除Snd.WS.OK标志。

检查TSopt选项;如果找到,将SEG.TSval保存在变量TS.Recent中
并打开Snd.TS.OK位。

将RCV.NXT设置为SEG.SEQ+1,IRS设置为SEG.SEQ,任何其他控制或文本
应排队等待稍后处理。应选择ISS并发送以下形式的SYN段:

<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>

如果Snd.WS.OK位打开,在此段中包含WSopt选项<WSopt=Rcv.Wind.Scale>。
如果Snd.TS.OK位打开,在此段中包含TSopt <TSval=my.TSclock,TSecr=TS.Recent>。
Last.ACK.sent设置为RCV.NXT。

SND.NXT设置为ISS+1,SND.UNA设置为ISS。连接状态应更改为SYN-RECEIVED。
请注意,任何其他传入的控制或数据(与SYN结合)将在SYN-RECEIVED状态下处理,
但不应重复处理SYN和ACK。如果侦听未完全指定(即外部套接字未完全指定),
则现在应填充未指定的字段。

第四其他文本或控制

...

如果状态是SYN-SENT,则

首先检查ACK位

...

第四检查SYN位

...

如果SYN位打开且安全性/隔间和优先级可接受,则RCV.NXT设置为SEG.SEQ+1,
IRS设置为SEG.SEQ,并且重传队列上因此被确认的任何确认应被删除。

检查窗口缩放选项 (WSopt);如果找到,将SEG.WSopt保存在Snd.Wind.Scale中;
否则,将Snd.Wind.Scale和Rcv.Wind.Scale都设置为零。

检查TSopt选项;如果找到,将SEG.TSval保存在变量TS.Recent中,
并在连接控制块中打开Snd.TS.OK位。如果设置了ACK位,
使用my.TSclock - SEG.TSecr作为初始RTT估计。

如果SND.UNA > ISS (我们的SYN已被确认),将连接状态更改为ESTABLISHED,
形成ACK段:

<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

并发送它。如果Snd.Echo.OK位打开,在此ACK段中包含TSopt选项
<TSval=my.TSclock,TSecr=TS.Recent>。Last.ACK.sent设置为RCV.NXT。

排队等待传输的数据或控制可以包括在内。如果段中有其他控制或文本,
则继续在下面第六步检查URG位的地方处理,否则返回。

否则进入SYN-RECEIVED,形成SYN,ACK段:

<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>

并发送它。如果Snd.Echo.OK位打开,在此段中包含TSopt选项
<TSval=my.TSclock,TSecr=TS.Recent>。

如果Snd.WS.OK位打开,在此段中包含WSopt选项<WSopt=Rcv.Wind.Scale>。
Last.ACK.sent设置为RCV.NXT。

如果段中有其他控制或文本,在达到ESTABLISHED状态后排队等待处理,返回。

第五,如果SYN或RST位都没有设置,则丢弃段并返回。

否则,

首先,检查序列号

  SYN-RECEIVED状态
ESTABLISHED状态
FIN-WAIT-1状态
FIN-WAIT-2状态
CLOSE-WAIT状态
CLOSING状态
LAST-ACK状态
TIME-WAIT状态

段按顺序处理。到达时的初始测试用于丢弃旧重复,
但进一步的处理按SEG.SEQ顺序完成。如果段的内容跨越新旧之间的边界,
则仅应处理新部分。

重新缩放接收到的窗口字段:

TrueWindow = SEG.WND << Snd.Wind.Scale,

并在以下步骤中使用"TrueWindow"代替SEG.WND。

检查段是否包含时间戳选项且Snd.TS.OK位打开。如果是:

如果SEG.TSval < TS.Recent,则测试连接是否空闲少于24天;
如果两者都为真,则段不可接受;遵循下面不可接受段的步骤。

如果SEG.SEQ等于Last.ACK.sent,则将SEG.ECopt保存在变量TS.Recent中。

对于传入段的可接受性测试有四种情况:

...

如果传入段不可接受,应发送确认作为回复(除非设置了RST位,
如果是,则丢弃段并返回):

<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

Last.ACK.sent设置为确认的SEG.ACK。如果Snd.Echo.OK位打开,
在此ACK段中包含时间戳选项<TSval=my.TSclock,TSecr=TS.Recent>。
将Last.ACK.sent设置为SEG.ACK并发送ACK段。发送确认后,
丢弃不可接受的段并返回。

...

第五检查ACK字段。

如果ACK位关闭,丢弃段并返回。

如果ACK位打开

...

ESTABLISHED状态

如果SND.UNA < SEG.ACK <= SND.NXT,则设置SND.UNA <- SEG.ACK。
还计算往返时间的新估计。如果Snd.TS.OK位打开,
使用my.TSclock - SEG.TSecr;否则使用重传队列中第一个段
发送以来经过的时间。重传队列上因此被完全确认的任何段...

...

第七,处理段文本。

ESTABLISHED状态
FIN-WAIT-1状态
FIN-WAIT-2状态

...

发送以下形式的确认:

<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

如果Snd.TS.OK位打开,在此ACK段中包含时间戳选项
<TSval=my.TSclock,TSecr=TS.Recent>。将Last.ACK.sent设置为确认的SEG.ACK,
并发送它。如果可能,应在不产生不当延迟的情况下,
将此确认捎带在正在传输的段上。

...