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