📄 tcp协议规范.htm
字号:
process"。如果有权利,则返回"error: connection does not exist"。</P>
<P align=justify>LISTEN状态</P>
<P align=justify>存在着的任何RECEIVE都会返回"error:
closing"的响应。删除TCB,然后进入CLOSED状态并返回。</P>
<P align=justify>SYN-SENT状态</P>
<P align=justify>删除TCB并返回"error: closing"响应给任何在队列中的SEND或RECEIVE。</P>
<P align=justify>SYN-RECEIVED状态</P>
<P
align=justify>如果没有发送SEND,而且没有等待发送的数据了,则形成并发送FIN数据段,进入FIN-WAIT-1状态;否则在进入ESTABLISHED状态后将命令保存在队列中等待处理。</P>
<P align=justify>ESTABLISHED状态</P>
<P
align=justify>将这一命令保存在队列中,直到所有正在进行的SEND完成后,形成并发送FIN数据段,然后进入FIN-WAIT-1状态。</P>
<P align=justify>在FIN-WAIT-1和FIN-WAIT-2状态下</P>
<P align=justify>严格地说,这将会是个错误,会收到"error: connection
closing"。只要第二个FIN没有发出,也可以收到一个"ok"响应。</P>
<P align=justify>CLOSE-WAIT状态</P>
<P align=justify>直到所有SEND命令完成后再将这个请求放入队列;然后发送FIN数据段,进入CLOSING状态。</P>
<P align=justify>在CLOSING,LAST-ACK和TIME-WAIT状态下返回"error: connection
closing"。</P>
<P align=justify> </P>
<P align=justify>ABORT调用</P>
<P align=justify>CLOSED状态</P>
<P align=justify>如果用户没有权利访问这个连接,返回"error: connection illegal for this
process"。如果有权利,则返回"error: connection does not exist"。</P>
<P align=justify>LISTEN状态</P>
<P align=justify>任何存在的RECEIVE都应该返回"error: connection
reset",删除TCB,进入CLOSED状态,然后返回。</P>
<P align=justify>SYN-SENT状态</P>
<P align=justify>对于所有在队列中的SEND和RECEIVE,都返回"connection
reset",删除TCB,进入CLOSED状态,然后返回。</P>
<P
align=justify>在SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2和CLOSE-WAIT状态</P>
<P
align=justify>发送数据段<SEQ=SND.NXT><CTL=RST>,对于所有在队列中的SEND和RECEIVE,都返回"connection
reset",;所有要进行传送或重新传送的数据段立刻进行,删除TCB,进入CLOSED状态,然后返回。</P>
<P
align=justify>在CLOSING,LAST-ACK和TIME-WAIT状态下返回"ok",删除TCB,进入CLOSED状态,然后返回。</P>
<P align=justify> </P>
<P align=justify>STATUS 调用</P>
<P align=justify>CLOSED状态</P>
<P align=justify>如果用户没有权利访问这个连接,返回"error: connection illegal for this
process"。如果有权利,则返回"error: connection does not exist"。</P>
<P align=justify>LISTEN状态</P>
<P align=justify>返回"state = LISTEN"和TCB指针。</P>
<P align=justify>SYN-SENT状态</P>
<P align=justify>返回"state = SYN-SEND"和TCB指针。</P>
<P align=justify>SYN-RECEIVED状态</P>
<P align=justify>返回"state = SYN-RECEIVED"和TCB指针。</P>
<P align=justify>ESTABLISHED状态</P>
<P align=justify>返回"state = ESTABLISHED"和TCB指针。</P>
<P align=justify>FIN-WAIT-1状态</P>
<P align=justify>返回"state = FIN-WAIT-1"和TCB指针。</P>
<P align=justify>FIN-WAIT-2状态</P>
<P align=justify>返回"state = FIN-WAIT-2"和TCB指针。</P>
<P align=justify>CLOSE-WAIT状态</P>
<P align=justify>返回"state = CLOSE-WAIT"和TCB指针。</P>
<P align=justify>CLOSING状态</P>
<P align=justify>返回"state = CLOSING"和TCB指针。</P>
<P align=justify>LAST-ACK状态</P>
<P align=justify>返回"state = LAST-ACK"和TCB指针。</P>
<P align=justify>TIME-WAIT状态</P>
<P align=justify>返回"state = TIME-WAIT"和TCB指针。</P>
<P align=justify>接收到数据段</P>
<P
align=justify>如果处于CLOSED状态,所有到达的数据都被抛弃。包括RST的也不例外。如果接收到的数据段不包括RST,则返回一个RST。对于发送TCP要选择它可以认知的确认和序列号。如果关闭ACK位,则序列号为0,格式如下:<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>如果打开ACK位,格式如下:<SEQ=SEG.ACK><CTL=RST>。</P>
<P
align=justify>如果处于LISTEN状态,首先检查RST,接收到的RST应该被忽略。下来应该检查ACK,如果连接处于LISTEN状态下,任何ACK都是错误的,应该返回RST段,它的格式如下:<SEQ=SEG.ACK><CTL=RST>。</P>
<P
align=justify>第三步应该检查SYN,如果SYN位设置了,检查安全性,如果接收数据段中的security/compartment与TCB中的不能匹配,返回RST段,格式如下:<SEQ=SEG.ACK><CTL=RST>。在SEG.PRC大于TCB.PRC的情况下,如果用户和系统允许,则设置TCB.PRC<-SEG.PRC,如果用户和系统不允许,发送RST段并返回。其格式如下:<SEQ=SEG.ACK><CTL=RST>。如果SEG.PRC小于TCB.PRC,继续进行。设置RCV.NXT为SEG.SEQ+1,IRS为SEG.SEQ中的值,其它控制信息和数据以后处理。应该选择ISS,并发送SYN段,其格式如下:<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>。SND.NXT设置为ISS+1,SND.UNA设置为ISS的值,连接状态改为SYN-RECEIVED。其它控制信息和数据将在SYN-RECEIVED状态中处理,但以于SYN和ACK的处理不应该重复。如果未完全指定LISTEN域,现在就应该指定了。</P>
<P
align=justify>第四步是处理其它数据和控制信息。其它的数据段(不包括SYN)应该有ACK,因此不要对它进行ACK处理。如果接收到RST段,则它是非法的。如果确实接收到了,抛弃它,直接返回。</P>
<P align=justify>如果处于SYN-SENT状态。首先检查ACK位,如果设置了ACK位,而且SEG.ACK =<
ISS或SEG.ACK >
SND.NXT,发送RST。(除非设置了RST位,如果这样,抛弃这个数据段直接返回)。RST段的格式如下:<SEQ=SEG.ACK><CTL=RST>。不用理会收到的数据段,直接返回。如果SND.UNA
=< SEG.ACK =< SND.NXT,那么ACK是可以接受的。</P>
<P align=justify>下一步检查RST位。在设置了RST的情况下,如果ACK是可以接受的,通知用户"error: connection
reset",抛弃接收到的数据段并进入CLOSED状态,删除TCB并返回。如果ACK不能接受,抛弃数据段返回。</P>
<P
align=justify>第三步检查安全性和优先级。如果security/compartment和TCB中的security/compartment不匹配,发送RST段。在发送RST段的时候,如果已经有ACK了,格式为:<SEQ=SEG.ACK><CTL=RST>,如果没有ACK,格式为<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>。在没有发现不匹配的时候,如果有ACK,段中的优先级必须和TCB中的匹配,如果不匹配,发送RST,其格式为:<SEQ=SEG.ACK><CTL=RST>;如果未发现不匹配,而且没有ACK的情况下,如果接收到的数据段中的优先级高于TCB中的优先级,在得到用户和系统许可的情况下可以将TCB中的优先级升高,如果用户或系统不许可,提高prec,然后以如下格式发送RST:<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>,如果接收数据段中的优先级小于TCB中的优先级则继续。在发送了RST后,抛弃数据段并返回。</P>
<P
align=justify>第四步检查SYN位。只有在ACK位是合法或没有ACK而且数据段中不包括RST的情况下才能进行这一步。如果设置了SYN位,而且security/compartment和优先级合法,那么RCV.NXT设为SEG.SEQ+1,IRS设为SEG.SEQ。SND.UNA应该增加和SEG.ACK相等,在重新发送队列中原来等待确认而现在已经被确认的数据段也被清除。如果SND.UNA
> ISS,改变连接状态为ESTABLISHED,形成下面格式的ACK段并发送:
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>。队列中用于发送的数据的控制信息也一起发送,如果段中没有数据或控制信息,则进行第六步,否则返回。如果SND.UNA
>
ISS不成立,形成SYN,ACK段,格式如下:<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>,并发送它。如果在段中没有数据或控制信息,待进入ESTABLISHED状态后再进行处理。</P>
<P align=justify>第五步,如果SYN或RST位没有设置,抛弃数据段返回。</P>
<P align=justify>下来我们来看看其它状态。首先应该检查序列号。在下面状态下</P>
<P align=justify>SYN-RECEIVED状态</P>
<P align=justify>ESTABLISHED状态</P>
<P align=justify>FIN-WAIT-1状态</P>
<P align=justify>FIN-WAIT-2状态</P>
<P align=justify>CLOSE-WAIT状态</P>
<P align=justify>CLOSING状态</P>
<P align=justify>LAST-ACK状态</P>
<P align=justify>TIME-WAIT状态</P>
<P
align=justify>段按顺序处理,首先抛弃重复的段,对于以后的处理要根据SEG.SEQ的大小进行。如果有的段内的新老内容重叠在一起,那只用处理新的那一部分。下面是对接收到的数据的可接受性测试中的四种情况:</P></FONT>
<TABLE cellSpacing=1 cellPadding=7 width="100%" border=1>
<TBODY>
<TR>
<TD vAlign=top width="15%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>段长度</FONT></P></BLOCKQUOTE></TD>
<TD vAlign=top width="17%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>接收窗口</FONT></P></BLOCKQUOTE></TD>
<TD vAlign=top width="68%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>测试</FONT></P></BLOCKQUOTE></TD></TR>
<TR>
<TD vAlign=top width="15%">
<BLOCKQUOTE><FONT face=宋体 size=3>
<P align=justify>0</FONT></P></BLOCKQUOTE></TD>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -