🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 网络基本功(二十六):Wireshark抓包实例分析TCP窗口及reset **转载请在文首保留原文出处:EMC中文支持论坛**[https://community.emc.com/go/chinese](https://community.emc.com/go/chinese) [![image001.gif](https://community.emc.com/servlet/JiveServlet/downloadImage/2-867817-107581/image001.gif)](https://community.emc.com/servlet/JiveServlet/showImage/2-867817-107581/image001.gif) ## 介绍 TCP最重要的机制之一是滑动窗口机制,以及用以控制TCP终端节点愿意接收的数据总量的流控机制。 TCP reset可以在几种情况下被发送。有一些是协议的正常工作过程,有一些则表明可能有问题。本节中,我们查找问题以及分析解决问题的方法。 本章讨论以上两个问题。 ## 更多信息 **TCP窗口问题:** TCP零窗口,零窗口探测,零窗口违例 TCP零窗口发生于接收方在TCP头部的window字段广播接收窗口零字节的时候。这一事件告知发送方停止发送数据,因为接收方缓存已满。这也表明接收方可能发生以下问题: * 服务器无法为进程分配组后的内存 * 应用碰到没有足够内存的问题,因此TCP需告知发送方停止发送数据 * 应用消耗太多内存因此操作系统要限制应用资源 TCP零窗口探测由发送方发出,以查看接收方的零窗口是否依然存在。这一消息通过发送下一字节数据给接收方,如果接收方回复窗口大小仍然为零,则发送方的探测计时器加倍。 TCP窗口违例:发送方忽略接收方的零窗口大小并发送额外字节数据。TCP零窗口违例表明协议栈中有TCP错误。为了检查是何问题,检查是否有以下事件: * 某一终端设备(服务器或客户机)报出终端设备故障 * 某一应用报出常规应用错误 * 应用中执行某一操作时报错,例如,打开一个表格,发送一份文件至打印机,创建一个报告,或其他操作。这种情况下,是应用问题。 TCP窗口更新 TCP将窗口更新发送至连接的对端,以表明缓存大小更改,并且准备好接受更高或更低的数据速率(缓存大小决定了发送方被允许的发送速率)。这一情况发生于: * TCP接收方从零窗口中恢复,告知发送方重新发送速率。这一情况下,无需进行处理,只需检查第一次导致零窗口的问题。 * TCP接收方频繁更改窗口大小。该情况下检查接收方被干扰的原因。可能是应用问题,内存问题,或终端设备上的其他问题。 看到这类现象无需担心,这就是TCP的工作机制。 TCP窗口已满 这一信息表明已发送的报文会完全填满接收方的接收缓存。发生于接收方没有对先前接收到的数据发出任何ACK确认信息,因此,这将会成为发送方从接收方收到ACK之前的最后一个报文数据。 这一事件的触发原因与触发零窗口的原因相同,是服务器或应用无响应的标志。典型实例如下图所示: [![image002.jpg](https://community.emc.com/servlet/JiveServlet/downloadImage/2-867817-107582/670-246/image002.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-867817-107582/image002.jpg) 上图中可以看到: 1. 报文183816,192.168.2.138告知192.168.1.58发送窗口已满。 2. 下一个报文,192.168.1.58发送一个信号至192.168.2.138,告知对方停止发送数据。这是一个零窗口信号。 3. 双方继续发送零窗口以及零窗口探测。 4. 连接的最后一个报文是192.168.2.138发送的RST报文,目的是断开连接。 5. 某些情况下零窗口可以通过窗口更改信息来回复。某些情况下可通过reset来关闭(可以是应用零窗口从而没有收到任何数据导致)。 工作原理 TCP滑动窗口机制如下: 1. 连接建立之后,发送方将数据发送至接收方,填入接收窗口。 2. 若干报文之后,接收方发送ACK至发送方,确认接收到其发送的字节数。发送ACK将接收窗口清零。 3. 这一过程持续下去,发送方向窗口中填入数据,接收方清空并发送确认信息。 4. 扩大接收窗口大小告知发送方增加吞吐量,减小窗口告知对方减小吞吐量。这一机制按照WS/RTT规则(随着TCP版本不同而有所改变): [![image003.jpg](https://community.emc.com/servlet/JiveServlet/downloadImage/2-867817-107583/670-198/image003.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-867817-107583/image003.jpg) 也可以通过TCP吞吐量图表和IO图来查看问题。在TCP吞吐量图表中,使用TCP trace图表,上面一行显示了窗口大小,与下面一行的距离表明窗口的剩余大小。没有距离表示零窗口。 [![image004.jpg](https://community.emc.com/servlet/JiveServlet/downloadImage/2-867817-107584/image004.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-867817-107584/image004.jpg) 两行之间的固定距离表明接收方工作良好。当两行渐渐靠近,表明发送方速度高于接收方。只要这两行没有重叠,TCP就会继续发送数据。 **TCP reset及原因:** 在可疑的链路或服务器两端连接Wireshark,开始抓包。观察抓包窗口的每一个窗口信息。TCP reset可以在几种情况下被发送。有一些是协议的正常工作过程,有一些则表明可能有问题。本节中,我们查找问题以及分析解决问题的方法。 reset是用以告知接收方断开连接的TCP信号,通过将RST标志位置1来发送。正常的操作过程中,TCP通过SYN信号打开连接,通过FIN信号关闭连接。TCP的一大特性在于有问题时,或只是为了更好的性能,它能够快速关闭连接。 无故障时发送reset TCP关闭连接的标准方式是通过FIN和FIN-ACK信号。为了关闭连接,用户需要四个报文:来自一方的FIN/ACK和ACK,以及另一方的同样报文。当你打开一个网页,可能同时打开了数十个连接(主页,新闻,广告,定期更新的图片等),要关闭所有这些有时需要数百个FIN和FIN-ACK报文。为了防止其发生,web服务器在很多情况下会在发送请求数据之后用reset断开连接。这是标准的做法,并取决于应用程序。 有故障时发送reset 某些情况下reset表明有故障发生(并不一定是通信故障): * **防火墙发送的reset**:当远端服务器尝试打开连接但没有结果时,也许会看到返回RST信号。这是防火墙阻隔连接的情况。下图中,可看到发送的每一个SYN都返回以RST。 [![image005.jpg](https://community.emc.com/servlet/JiveServlet/downloadImage/2-867817-107585/670-257/image005.jpg)](https://community.emc.com/servlet/JiveServlet/showImage/2-867817-107585/image005.jpg) * **由于收发一方有问题发送的reset**:可能的原因如: * 五个连续没有收到ACK回复的重传。当发送方没有收到任何重传回复,它就会发送一个reset信号到对端,告知其断开连接。 * 另一个原因是连接之上几分钟都没有任何数据(分钟数取决于系统默认)。打开连接的一方通常会发送reset(但并不总是会这样做,取决于实现方式)。 ## 参考 Network Analysis Using Wireshark Cookbook