《TCP/IP详解卷3:TCP事务协议、HTTP、NNTP和UNIX域协议》 —3.2 客户重新启动
3.2 客户重新启动
客户一旦启动,客户-服务器事务过程也就开始了。客户程序调用sendto函数,即在路由表中为对端服务器增加一个表项,其中tao_ccsent的值初始化为0(表示未定义)。于是TCP协议就会发送CCnew选项而不是发送CC选项。服务器上的TCP协议收到CCnew选项后就执行常规的三次握手操作,其过程可见图3-1所示的Tcpdump的输出(不熟悉Tcpdump操作及其输出的读者可参见卷1的附录A。在跟踪观察这些分组的时候,不要忘了SYN和FIN在序号空间中各占用一个字节)。
从第1行的CCnew选项可以看出,客户端tcp_ccgen的值为1。在第2行,服务器对客户的CCnew给出了回应,服务器的tcp_ccgen值为18。服务器给客户的SYN发出确认,但不确认客户的数据。由于收到了客户的CCnew选项,即使服务器在其单机高速缓存中有该客户的表项,它也必须完成正常的三次握手过程。只有当三次握手完成以后,服务器的TCP协议才能把收到的300字节数据提交给当前的服务进程。
第3行显示的是三次握手过程的最后一个报文段:客户对服务器发出SYN的确认。在这个报文段中客户将FIN重传,但不包括300字节数据。服务器收到该报文段后,立刻确认了收到的数据和FIN(第4行)。与一般的报文段不同的是,这个确认是即时发出的,没有被耽搁。这么做是为了防止客户第1行发送数据后超时而重传。
第5行显示的是服务器给出的应答以及服务器的FIN,第6行中客户对服务器的FIN和应答都做了确认。注意,第3~6行中都有CC选项,而CCnew和CCecho选项则分别只出现在第1和第2个报文段中。
从现在开始,我们不再明确地在T/TCP报文段中标记NOP了,因为NOP不是必需的,而且会把图搞复杂。插入NOP,使选项长度保持为4字节整数倍的做法是出于对提高主机性能的考虑。
机敏的读者可能会注意到,客户端刚刚重新启动时,客户TCP协议所用的初始序号(ISN)与卷1中习题18.1所讨论的一般模式不一样。而且,服务器的初始序号是个偶数,这在通常从伯克利演变而来的实现中是从来没有的。其原因在于这里的连接所使用的初始序号是随机选取的,而且每隔500 ms对内核的初始序号所加的增量也是随机的。这种改动有助于防止序号攻击,具体内容可见参考文献[Bellovin 1989]。这种改动是1994年12月一次很有名的因特网侵入事件发生后,首先在BSD/OS 2.0然后在4.4BSD-Lite2中加入的[Shimomura 1995]。
时序图
图3-2给出的是图3-1所描述的报文段交换过程的时序图。
图中,包含数据的第1和第5这两个报文段用粗黑线标记。图的两侧还分别标注了客户和服务器收到报文段后各自发生的状态变迁。开始的时候,客户进程调用sendto函数并指定MSG_EOF标志后进入SYN_SENT*状态。服务器收到并处理了第3个报文段后发生了两次状态变迁。先是处理客户对服务器发出SYN的确认后,连接的状态由SYN_RCVD变迁到ESTABLISHED状态;紧接着处理客户发来的FIN又变迁到CLOSE_WAIT状态。当服务器向客户发出设置了MSG_EOF标志的应答后,即进入LAST_ACK状态。注意,客户在第3个报文段中重传了FIN标志(回忆一下图2-7)。
- 点赞
- 收藏
- 关注作者
评论(0)