Transmission Control Protocol, TCP 传输控制协议( 三 )



(a) 决定一些发送了的但未确认的序列号;
(b) 决定所有的序列号都已经收到了;
(c) 决定下一个段中应该包括的序列号 。
对于发送的数据TCP要接收确认,处理确认时必须进行下面的比较操作:
SND.UNA = 最老的确认了的序列号;
SND.NXT = 下一个要发送的序列号;
SEG.ACK = 接收TCP的确认,接收TCP期待的下一个序列号;
SEG.SEQ = 一个数据段的第一个序列号;
SEG.LEN = 数据段中包括的字节数;
SEG.SEQ SEG.LEN-1 = 数据段的最后一个序列号 。
请注重下面的关系:
SND.UNA < SEG.ACK =< SND.NXT
假如一个数据段的序列号小于等于确认号的值,那么整个数据段就被确认了 。而在接收数据时下面的比较操作是必须的:
RCV.NXT = 期待的序列号和接收窗口的最低沿;
RCV.NXT RCV.WND-1 = 最后一个序列号和接收窗口的最高沿;
SEG.SEQ = 接收到的第一个序列号;
SEG.SEQ SEG.LEN-1 = 接收到的最后一个序列号;
上面几个量有如下关系:
RCV.NXT =< SEG.SEQ < RCV.NXT RCV.WND 或 RCV.NXT =< SEG.SEQ SEG.LEN-1 < RCV.NXT RCV.WND
测试的第一部分是检查数据段的开始部分是否在接收窗口中,第二部分是检查数据段的结束部分是否也在接收窗口内;上面两个检查通过任何一个就说明它包括窗口要求的数据 。实际中的情况会更复杂一些,因为有零窗口和零数据段长,因此我们有下面四种情况:
段长度
接收窗口
测试
0
0
SEG.SEQ = RCV.NXT
0
>0
RCV.NXT =< SEG.SEQ < RCV.NXT RCV.WND
>0
0
不可接受
>0
>0
RCV.NXT =< SEG.SEQ < RCV.NXT RCV.WND或RCV.NXT =< SEG.SEQ SEG.LEN-1 < RCV.NXT RCV.WND
请注重接收窗口的大小可以为零,在窗口为零时它只用来接收ACK信息,因此对于一个TCP来说,它可以使用零大小窗口在发送数据的同时接收数据 。即使接收窗口的大小为零,TCP必须处理所有接收到信息的RST和URG域 。
我们也应用计数的方式保护了一些特定的控制信息,这是通过隐式地使用一些控制标记使数据段能够可靠地重新发送(或确认)为达到的 。控制信息并不在段数据空间中传送,因此,我们必须采用隐式指定序列号进行控制 。SYN和FIN是需要保护的控制量,这两个控制量也只在连接打开和关闭时使用 。SYN被认为是在第一个实际数据之间的数据,而FIN是最后一个实际数据之后的数据 。段长度(SEG.LEN)包括数据和序列号空间,假如出现了SYN,那么SEG.SEQ是SYN的序列号 。
初始序列号选择
协议对于特定连接被重复使用没有什么限制 。连接是由一对套接字定义的 。新的连接实例被定义为连接的另一次恢复,这就带来了问题:TCP假如确定多个数据段是从以前连接的另一次恢复中取得的呢?这个问题在连接迅速打开和关闭,或因为内存原因被关闭然后又迅速建立后显示非凡突出 。
为了避免混乱,用户必须避免因此恢复使用某一连接,而使序列号发生混乱 。我们必须保证序列号的正确性,即使TCP失败,根本不知道以前的序列号是什么的情况下也要保证序列号的正确性 。当新的连接被创建时,产生一个新的初始序列号(ISN)产生子,它用来选择一个新的32位ISN 。产生子和32位时钟的低度位字节相关,低位字节的刷新频率大概是4微秒,因此ISN的循环时间大概是4.55小时 。因此我们把网络包的最长生存时间(MSL)小于4.55小时,因此我们可以认为ISN是唯一的 。对于每个连接都有发送序列号和接收序列号,初始发送序列号(ISS)由发送TCP选择,而初始接收序列号是在连接建立过程中产生的 。

推荐阅读