跳到主要内容

附录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,
并发送它.如果可能,应在不产生不当延迟的情况下,
将此确认捎带在正在传输的段上.

...