天天看点

《Wireshark网络分析的艺术》—被误解的TCP

本节书摘来自异步社区《wireshark网络分析的艺术》一书中的被误解的tcp,作者林沛满,更多章节内容可以访问云栖社区“异步社区”公众号查看。

被误解的tcp

wireshark网络分析的艺术

人一旦形成某种思维定势,就很难再改变了。知道我收到最多的读者来信是问什么吗?“林工,有些tcp包发出去之后没有看到对应的ack,算不算丢包啊?”这个问题让我很是好奇,明明rfc上没有这样的规定,为什么总有读者觉得每一个数据包都应该有对应的ack呢?后来才注意到,很多提问者是做网站开发出身的,已经习惯了每个http请求发出去,就一定会收到一个http响应(见图1),因此就把这个模式套到了tcp上。其实不止http,绝大多数应用层协议都采用这种一问一答的工作方式。

《Wireshark网络分析的艺术》—被误解的TCP

tcp当然也可以采用这种方式,但并非必要。就像我们不用每天都跟公司算一次工钱,而是攒到月底结算一样,数据接收方也可以累积一些包才对发送方ack一次。至于ack的频率,不同的操作系统有不同的偏好,比如我实验室中的linux客户端喜欢每收到两个包ack一次,见图2。

《Wireshark网络分析的艺术》—被误解的TCP

而windows客户端则懒得多,隔好多个包才ack一次,见图3的97号包。

《Wireshark网络分析的艺术》—被误解的TCP

这两种方式都是正常的,但linux对流量更“大手大脚”一点,因为纯ack也算流量的。其实在网络带宽越来越大的今天,人们已经不在乎这种小流量了。不过手机操作系统还是要慎重考虑的,毕竟蜂窝数据是按流量计费的,能省一点是一点。我的安卓手机就是每收到一个包都会ack的,想到这里我的心都在滴血。图4是我在微博上打开一张美女图时产生的流量,你看这些密密麻麻的纯ack,每个都白费我40字节的流量。

《Wireshark网络分析的艺术》—被误解的TCP

也许以后会有手机厂商优化它,然后以此作为卖点。如果是从我这本书里学到的,请为它命名“林朗台算法”。

既然接收方不一定收到每个包都要ack,那发送方怎么知道哪些包虽然没有相应的ack,但其实已经送达了呢?记住,ack是有累积效应的,它隐含了“在此之前的其他包也已收到”的意思,比如图3中第97号包的ack=65701不仅表示收到了96号包(其seq+len=64273+1428=65701),而且暗示之前的其他包也都收到了。因此86~95号包虽然没有被显式ack,但发送方知道它们也已经被送达了。

另一个对tcp的广泛误解则和udp相关。有不少技术人员认为tcp的效率低,因为其传输过程中需要往返时间来确认(ack)。而udp无需确认,因此能不停地发包,效率就高了。事实真的如此吗?这其实是对tcp传输机制的严重误解。我们可以假设一个场景来类比tcp的工作方式:有大批货物要从a地运往b地。如果只用一辆货车来运的话,马路上就只有一辆车在来回跑(回程相当于tcp的ack包),效率确实很低,对tcp的误解可能也出自这个原因。但如果在不塞车的前提下尽量增加货车数量,使整条马路上充满车,总传输效率就提高了。tcp发送窗口的意义相当于货车的数量,只要窗口足够大,tcp也可以不受往返时间的约束而源源不断地传数据。这就是为什么无论在局域网还是广域网,tcp还是最受欢迎的传输层协议。

当然tcp确实也有因为往返时间而降低效率的时候,比如在传输小块数据的场景。本来能在1个往返时间完成的小事,却要额外耗费3次握手和4次挥手的开销,dns查询就符合这种场景。目前http基本建立在tcp连接上,所以也会因为tcp的三次握手而增加延迟。你可能听说过google发布的quic(quick udp internet connection)协议,它就是为了消除tcp的延迟而设计的代替品。在某些领域可以视为tcp的竞争对手,目前在google的网站上已经可以试用了。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。