TCP 超时与重传应该是 TCP 最复杂的部分之一了;
Windows 和 Linux 对这部分的实现有所不同,但是算法基本上还是差不多的;
超时重传是 TCP 保证可靠传输的基础;
当 TCP 在发送数据时,数据和 ack 都有可能会丢失;
因此,TCP 通过在发送时设置一个定时器来解决这种问题。如果定时器溢出还没有收到确认,它就重传数据;
无论是 Windows 还是 Linux,关键之处就在于超时和重传的策略,需要考虑两方面:
- 超时时间设置
- 重传的频率(次数)
目前来说,在 Linux 较高的内核版本中,比如 3.15 中,已经有了至少 9 个定时器:超时重传定时器,持续定时器,ER延迟定时器,PTO定时器,ACK延迟定时器,SYNACK定时器,保活定时器,FIN_WAIT2定时器,TIME_WAIT定时器。
这实在是太多了,对初学者来说,我们重点掌握以下 4 个:
- 超时重传定时器(retransmit)
- 持续定时器(persist)
- 保活定时器(keepalive,这和 HTTP 协议中的 keepalive 不是同一个概念)
- TIME_WAIT 定时器
一个超时重传的例子

图1 超时重传
本实验所使用的程序路径为 unp/program/echo/processzombie/echo.cc
,你可以直接使用 make
命令进行编译。
- 服务器端启动方式
$ ./echo -s -h flower // 或者你可以这样写 ./echo -s -h 192.168.166.47,flower 是我其中一台 linux 主机的名字
- 客户端启动方式
$ ./echo -h flower // 或者你可以写 ./echo -h 192.168.166.47
当客户端连接成功后,发送一行数据'helloworld'
,对方回射回来,一切正常,接下来,将服务器主机 flower 断网,然后客户端再次发送数据 'hehe'
。
大约等等了 16 分钟左右(图2),客户端返回一个错误:No route to host.

图2 客户端等待约 16 分钟后返回错误

因为在同一个网段,主机 sun 发送了17×3=51 次 ARP 请求,每发 3 次 ARP 就等 50 s 左右。