首页 > 代码库 > TCP协议之差错控制

TCP协议之差错控制

说明 本文仅供学习交流,转载请标明出处,欢迎转载!

 本文是以下文献相关内容的总结

[1] 《TCP/IP详解 卷1:协议》
[2] 《TCP/IP协议族 第4版》
[3] 《计算机网络 第5版》

        TCP是一种面向连接的、可靠的、基于字节流的协议。可靠性指的是发送应用程序把数据流交付给TCP后,能够把数据流按序地、无差错地交给接收端的接收端的应用程序。TCP通过差错控制来提供可靠性,TCP差错控制包括:(1)检测并重传受损伤的报文段;(2)重传丢失的报文段;(3)丢弃重传的报文段并重传该报文段的ACK;(4)保证接收缓冲区的报文段按序交给接收端的应用程序。

       FAQ1:TCP如何检测数据报是否损伤?

        TCP接收端在收到报文段后,在报文段的首部加上伪首部后,连同数据部分一块计算检验和,如果计算结果为全1,说明数据没有收到损伤。

       FAQ2:接收方在什么时候产生ACK报文段? 

       (1)当接收方收到发送方发来的按序到达的报文段时,就发送过一个ACK报文段;

       (2)当收到的报文段的序号比期望的报文段的序号大时,接收方立即发送之前那个为收到的序号(即还是之前那个期望的序号);

       (3)接收方收到一个重复的报文段时,丢弃该报文段,并立即向发送端发送该报文段的ACK。

       FAQ3:发送方何时重传?

        情况一:当发送方发送一个数据段出去时,会启动重传计时器,若在RTO内没有收到该数据段的ACK,则发送端则重传该数据段,该情况叫超时重传

        情况二:当发送端收到接收端发送过来的三个对重复的ACK时(即三个期望收到的报文段相同时),即便RTO为到时,发送端也重传接收方期望的那个数据段,该情况叫快重传

       FAQ4:接收方如何处理失序到达的报文段?

        TCP并不会丢弃失序到达的报文段,而是将这些失序达到的报文段临时存放在接收缓冲区,并把它们标志位失序报文段,直到确实的报文段到齐。一定要记住:TCP永远都不会将失序的报文段交给接收进程

       FAQ5:发送端与接收端何时可能产生死锁现象?TCP是如何解决该死锁僵局的?

       当接收端向发送端发送一个零窗口报文段(报文段首部中窗口值的大小设置为0),发送端就停止向接收端发送报文段。后来接收端想通知发送端,让发送端接着发送数据时,便向发送端发送一个非零窗口报文段。不幸的是,该报文段在路上丢失了。而接收端以为该非零报文段已经发送给发送端,于是便傻乎乎地等待发送端发送数据过来。而发送端由于没有收到接收方的非零窗口报文段,于是便在那安逸地休息,随时等待接收方的非零窗口报文的通知。于是两端都傻乎乎地等,陷入“死锁”的状态。

       为了避免这一死锁的状态,TCP为发送端设置了一个持续计时器(persistent timer),当发送端收到接收端发来的零窗口报文段时,并启动该持续计时器,便等待着接收方的非零通知。如果一直没收到接收方的通知,持续计时器又超时了的时候,发送端便向接收方发送一个“探测报文段”,该探测报文仅携带1B的数据,该探测报文会消耗一个序号,但特殊的是,该探测报文段的序号永远不需要确认。该探测报文段的目的是仅仅是促使TCP接收端重传一个确认,该确认的内容包括接收端希望发送端的发送窗口的大小作为回复,即:如果接收端希望发送端的窗口大小仍然是0,那么发送端在收到该确认报文后,便会重置该持续计时器;如果接收方期望发送发的窗口不是0,则该僵局便打破了。

      注意:即便发送发收到了零窗口设置的报文段,发送端也能接收这几种报文段:探测报文段、ACK报文段和携带紧急数据的报文段