Wireshark 分析艺术

一,Wireshark 实战操作

界面的操作分析

三板斧之一:查看统计、属性信息

性能分析三板斧之一:

【统计捕获文件属性】 Statistics Summary,查看文件属性信息,如平均速度、包大小、包数等等

判断流量高低峰、是否过载

三板斧之二:查看分析专家信息

性能分析三板斧之二:

【分析专家信息】 Wireshark Analyze Expert Infos Notes,查看抓包的统计信息

查看是否有 Notes、Warnings、errors 之类的信息,看看是否有相关警告和错误,判断网络质量、重传乱序等

三板斧之三:查看服务响应时间

性能分析三板斧之三:

【统计服务响应时间】 statistics Service Response Time xxxxx(如:ONC-RPC Program:NFS)

查看各项操作的服务响应时间,判断是否过载

将 seq 使用相对值来替代真实值

EditPreferencesProtocolsTCP,勾选 Relative Sequence Numbers

启用之前就是相对值了。

查看 TCP StreamGraph

Statistics TCP StreamGraph TCP Sequence Graph(Stevens)

查看数据传输情况,如传输的是否均匀、是否有 TCP Zero Windows 之类的

字段含义&提示信息

字段含义就是 wireshark 的一些提示信息,也就是 wireshark 抓包的一些 info 信息,这些提示信息都是 Info 这一栏中体现。

1,[Packer size limited during caputre]

如果某个包被标记提示 [Packer size limited during caputre],说明这个包没有抓全,可以进一步查看下面的 frame 信息。一般这个情况是抓包的姿势不对。某些操作系统中,tcpdump 默认只抓取每个帧的前 96 个字节,因此 tcpdump 抓包的时候,可以通过 -s 参数指定要抓取的字节数

2,[TCP ACKed unseen segment]

如果wireshark发现被Ack的那个包没有抓到,就会提示 [TCP ACKed unseen segment],不过这个提示大部分情况都可以忽略。因为大都情况下,刚开始抓包的时候,都是只抓到了后面的 Ack 而没有抓到前面的 ACK

3,[TCP Previous segment not captured]

TCP数据传输中,除了三次握手和四次握手之外,同一台机器发出的数据段应该是连续的,即后一个包的Seq等于前一个包的Seq+Len,正确情况都应该是这样;如果发现后一个包的Seq大于前一个包的Seq+Len,那么就说明中间丢了一段数据,如果丢失的数据在整个网络包中都找不到,wireshark就会提示 [TCP Previous segment not captured]

出现这种情况的两个可能性:

  • 数据包真的丢了
  • 数据包并没有真丢,只是抓包工具漏掉了
    • 如果确认 Ack 包中包含了没有抓到的包,那就是抓包工具漏掉了,否则就是真丢了
4,[TCP Out-of-Order]

TCP数据传输中,除了三次握手和四次握手之外,同一台机器发出的数据段应该是连续的,即后一个包的Seq等于前一个包的Seq+Len,正确情况都应该是这样;或者说后一个包的Seq应该会大于等于前一个包的Seq+Len,如果wireshark发现后一个包的Seq小于前一个包的Seq+Len,那么就认为是乱序了,就会提示 [TCP Out-of-Order]

一般而言,小跨度的乱序影响不大,如果是大跨度的乱序则会导致快速重传。举例如下,如果一个包的顺序是 1、2、3、4、5 被打乱成 2、1、3、4、5 则属于小跨度乱序,影响不大;如果被打乱成 2、3、4、5、1,则会触发足够多的 Dup ACK,从而导致 1 号包的重传。

5,[TCP Dup ACK]

当乱序或者丢包发生时,接收方就会收到一些Seq号比期望值大的包,TCP协议每收到一个这种包就会ACK一次期望的Seq值,通过这个方式告知发送方,因此就产生了一些重复的Ack。Wireshark抓到这些重复的Ack就会提示 [TCP Dup ACK].

6,[TCP Fast Retransmission]

当发送方连续收到3个或者以上 [TCP Dup ACK] 时,就意识到之前发的包可能丢了,于是根据 RFC 的规定就会开始快速重传。[TCP Dup ACK] 是接收方回应给发送方的,因此发送方就能够感知到并当连续收到 3 个以上的时候就开启快速重传。

快重传算法规定,发送方只要一连收到 3 个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计数器时间到期。

7,[TCP Retransmission]

如果一个包真的丢了,又没有后续包可以在接收方触发[Dup Ack],那么就不会开启快速重传,这种情况发送方只能等到超时后再发送重传,超时重传的包就会被wireshark标记并提示 [TCP Retransmission]

TCP 超时与重传应该是 TCP 最复杂的部分之一,超时重传是 TCP 保证可靠传输的基础。当 TCP 在发送数据时,数据和 ack 都有可能会丢失,因此,TCP 通过在发送时设置一个定时器来解决这种问题。如果定时器溢出还没有收到确认,它就重传数据。关键之处就在于超时和重传的策略,需要考虑两方面:

  • 超时时间设置
  • 重传的频率(次数)

在 Linux 较高的内核版本中,比如 3.15 中,已经有了至少 9 个定时器:超时重传定时器,持续定时器,ER 延迟定时器,PTO 定时器,ACK 延迟定时器,SYNACK 定时器,保活定时器,FIN_WAIT2 定时器,TIME_WAIT 定时器。

8,[TCP zerowindow]

TCP包中“win=xxx”代表接收窗口的大小,表示这个包的发送方当前还有多少缓冲区可以接受数据。当wireshark发行一个包中的“win=0”时,就会标记提示 [TCP zerowindow],表示缓冲区已经满了,无法再接收数据了。

一般的,在缓冲区满之前,窗口大小应该是逐渐减小的过程。

9,[TCP window Full]

如果一个包的发送方已经把对方所声明的接收窗口大小耗尽了,就会被wireshark标记为 [TCP window Full]。比如某一端在握手时声明自己的接收窗口只有 65535,也就意味着对端最多只能给他发送 65535 字节的数据而无需确认,即“在途字节数”最多只能是 65535,当 wireshark 计算出对端已经有 65535 字节未被确认时,就会发生这个提示。

[TCP window Full]和上面的[TCP zerowindow]比较容易混淆,前者表示这个包的发送方暂时没有办法再发送数据了;后者表示这个包的发送方没有办法再接收数据了;两者都会意味着要暂停数据传输

10,[TCP segment of reassembled PDU]

只有在EditPreferencesProtocolsTCP菜单里启用了 Allow sub dissector to reassemble TCP streams 后,才有可能收到这个提示。这个表示可以把属于同一个应用层 PDU 的 TCP 包虚拟的集中起来

11,[Continuation to]

只有在EditPreferencesProtocolsTCP菜单里关闭了 Allow sub dissector to reassemble TCP streams 后,才有可能收到这个提示。

12,[Time-to-live-exceeded(Fragment reasembly time execeeded)]

(Fragment reasembly time execeeded)表示这个包的发送方之前收到了一些分片,但是由于某些原因导致迟迟无法组装起来。

比如传输过程中有一些分片被丢包了,那么接收方就无法组装起来,然后就通过这个 ICMP 的方式告知发送方

ICMP 是(Internet Control Message Protocol)Internet 控制报文协议。它是 TCP/IP 协议族的一个子协议,用于在 IP 主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。

二,Wireshark 分析 TCP 协议

TCP 抓包协议基础

TCP 控制字段

在 TCP 层,有个 FLAGS 字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG.

抓包显示的控制字段形态如下:

[SYN] :建立连接、发起包 [FIN] :关闭连接、结束包 [PSH] :DATA 数据传输 [ACK] :ACK 回应 [RST] :RESET、连接重置

另外两个常用字段:

[Len] :数据包长度 [Seq] :数据包序列号

ACK 是可能与 SYN,FIN 等同时使用的,比如 SYN 和 ACK 可能同时为 1,它表示的就是建立连接之后的响应,如果只是单个的一个 SYN,它表 示的只是建立连接

当出现FIN包或RST包时,我们便认为客户端与服务器端断开了连接 当出现 SYN 和 SYN+ACK 包时,我们认为客户端与服务器建立了一个连接

抓包方向(client or server)
  • 抓包的时候,不管是通过 wireshark 抓包,还是通过 tcpdump 抓包,都需要看看是从客户端方向抓包,还是从服务端方向抓包,不同的方向,抓包的情况完全不一样,因为网络(公网、实际环境)上有很多异常情况发生。
TCP 的 Ack

对应 http 而言,一般就是 requestreponse,一问一答。但对应 TCP 而言,并不一定每个包都会 ACK。TCP 的 ACK 是一种累积的 ACK,也就是表示在我这个 ACK 之前的所有其他 ACK 都已经确认收到了。

比如,97 号包的 ACK=65701,96 号包的 Seq+Len=64273+1428=65701,那么就是表示 97 号的 ACK 是对 96 号的回应,也就是 96 号之前的其他没有被显示 ACK 的包,其实都已经通过 97 号包 ACK 了,这样发送方也就知道了在 96 号之前发出去的所有包对方都已经收到并 ACK 了。

MSL、TTL、RTT
  • MSL(Maximum Segment Lifetime),表示“报文最大生存时间”,是所有报文都遵循的在网络上存在的最长时间,超过这个时间报文将被丢弃
    • RFC 793 中规定 MSL 为 2 分钟,实际应用中常用的是 30 秒,1 分钟和 2 分钟等。
    • 2MSL 即两倍的 MSL,TCP 的 TIME_WAIT 状态也称为 2MSL 等待状态
  • TTL(Time to live),表示生存时间,是 ip 头的一个域,生存时间是由源主机来设置一个初始值,但 TTL 不是存的具体时间,而是表示可以经过的最大路由数。
    • 根据 RFC 1812,一个网络包的 TTL 每减去 1 就表示它经过一次路由。一般 TTL 的初始值为 64,如果某个 ACK 包的 TTL 是 62,则意味着是是距离此设备两跳的设备发出来的。
    • TTL在wireshark抓包中的形态如 Time to live: 62
    • TTL=0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机
    • 一般在缓存、连接心跳中也用到 TTL 这个,他们和 TCP 协议中的 TTL 是有区别的,缓存、连接心跳中的 TTL 表示的就是数据缓存 or 剩余的时间。
  • RTT(round-trip time),表示客户到服务器往返所花时间,TCP 含有动态估算 RTT 的算法
    • TCP 会持续估算一个给定连接的 RTT,因为 RTT 受网络传输拥塞程序的变化而变化
MAC 地址解析

Protocol = ARP Source 和 Destination 都是MAC地址格式如 00:60:48:ff:12:31

抓包分析中,如果网络不通,发出去收不到 ACK 等等之类的,要再进一步看看每个包的 MAC 地址是否正确,反之有多个 MAC 地址导致的一些问题

TCP 握手和挥手协议

TCP 三次握手&判断回包
  • 三次握手协议
    • clientserver : [SYN] Seq=X win=xxx Len=0 MSS=xxx
    • serverclient : [SYN, ACK] Seq=Y,ACK=X+1 win=xxx Len=0 MSS=xxx
    • clientserver : [ACK] Seq=X+1,Ack=Y+1 win=xxx Len=0
  • 抓包数据,如何判断一个包是上一个包的回包呢?根据 TCP 协议,下一个包的 Ack 的值如果等于上一个包的 Seq + Len,则表示是其回包
    • 上一个和下一个,很多情况下并不是连续的,也行下一个回包距离上一个包已经过了很多包了,因为重传、延迟的原因的
  • 三次握手的时候会相互声明各自的 MSS
TCP 四次挥手&三次挥手
  • TCP 四次挥手协议
    • clientserver : FIN Seq=X,ACK=Y
    • serverclient : Seq=Y,ACK=X+1
    • serverclient : FIN Seq=Y,ACK=X+1
    • clientserver : Seq=X+1,Ack=Y+1
  • 正常而言,都会有这样的四次挥手,但是如果有延迟确认,那么四次挥手就变成了 3 次挥手,省掉了四次挥手中的第二个包
    • clientserver : FIN Seq=X,ACK=Y
    • serverclient : FIN Seq=Y,ACK=X+1
    • clientserver : Seq=X+1,Ack=Y+1

TCP 拥塞控制算法

在途字节数
  • 在途字节数【bytes in flight】,表示的是已经发送出去,但是还没有被确认的字节数,这个确认指的是对端发出 ACK 确认,这个就是所谓的网络承载量;如果在途字节数超过网络承载量,那么就会发生丢包重传
    • 这个“当前”仅仅从抓包上的网络包序号去看就可以了,并不需要这两个包有什么关系,也正因为这两个包没有关系,所以才是计算出在途字节数的方式
    • 这个Len,一般而言,不应该超过TCP的MSS(最大数据字段),这个值是 1388,注意对比 MTU(1500)
    • 在途字节数 = 当前发送方的【Seq + Len】 - 当前接收方的【ACK】
网络拥塞
  • 网络拥塞点:超过网络承载量而导致的网络拥塞。发生拥塞时的在途字节数就是该时刻的网络拥塞点,估算网络拥塞点只需要简单找到拥塞时的在途字节数即可
    • 从发送方的视角,相当于是站在了 CPU 视角,这样抓包看到的应该是分段前的打包。从接收方视角,相当于是站在了网卡视角,那么看到的就应该是分段后的多个小包
    • LSO 出现的意义在于目前网卡经常是千兆、万兆,这样 CPU 的负担很重。比如 625MB/s 的网络流量大约需要耗费 5GHz 的 CPU,因此为了缓解 CPU 的负担,就把一些分段的工作直接交给网卡去执行了,
    • 取最小值是因为这样最保守,这样才能真正保证网络不会拥塞;取完之后要设置 Linux 的发送窗口
    • 假如 Seq+Len-Ack = 103122,这个单位表示字节,也就是 100KB,这个 100KB 就是最大的发送窗口,因此需要设置 Linux 系统中发送窗口的值
    • 拥塞的特征就是连串的丢包、丢包后又会重传;wireshark、tcpdump 等抓包工具可以标识出重传包
    • 根据抓包工具,找到一连串重传包中的第一个包,然后根据该包重传的 Seq 值找到对应的原始包,最后,计算该原始包发送时刻的在途字节数,这个就标识当前的拥塞点
    • Wireshark Analyze Expert Info Notes 菜单可以看到重传统计
    • 通过在途字节数只是估算 网络拥塞点,并不一定很精确,可以采样多次然后找到合适的值;多次采样后的数据,其实保守的话应该取最小值而不是平均值
    • 前面有说的,数据包的 Len 最大不应该超过 1388,但是实际抓包分析过程中,却会发现实际的 Len 可能是 1338 的两倍或者 N 倍,这个是什么原因呢?这是因为有一个所谓的 LSO。
    • 一般网络工作方式是:应用层把产生的数据交给 TCP 层,TCP 再根据 MSS 大小进行分段,分段由 CPU 负责进行,最后再交给网卡
    • 如果启用了 LSO:TCP 层就把大于 MSS 的数据块直接交给了网卡,让网卡去负责分段工作。

一些实战经验告诉我们,Wireshark ->Analyze -> Expert Info -> Notes 统计中的重传率如果超过了 0.1%,就需要采取一些措施了。但是现实网络环境下,要低于 0.01%的重传是基本不可能的。

发送窗口
  • 客户端发送窗口的两个因素:网络上的拥塞窗口(cwnd)和服务器上的接收窗口
    • 如果是“慢启动”阶段,那么下一个 RTT 的包的 cwnd 应该要远远大于上一个包的 cwnd
    • 如果是“拥塞避免”阶段,那么下一个 RTT 的包的 cwnd 应该要增加一个 MSS(以太网中的 MSS 约为 1460 字节)。
    • 如果不符合上述两种情况,比如 cwnd 增长的非常慢,那么就需要根据 cwnd 的计算方式去分析了
    • cwnd 的增长方式是:先“慢启动”、再进入“拥塞避免”,前者起点低但是能够快速增长、后者起点高但是每一个 RTT 只能增加一个 MSS(RTT 指往返时间,也就是到了下一个从同一个方向传输的包)
    • 根据抓包的数据,点开详情,查看其“Bytes in flight”值,可以简单等同与 cwnd
TCP Nagle 算法和延迟确认 Delayed ACK
  1. Nagle 算法:
    • 是为了减少广域网的小分组数目,从而减小网络拥塞的出现;
    • 该算法要求一个 tcp 连接上最多只能有一个未被确认的未完成的小分组,在该分组 ack 到达之前不能发送其他的小分组,tcp 需要收集这些少量的分组,并在 ack 到来时以一个分组的方式发送出去;其中小分组的定义是小于 MSS 的任何分组;
    • 该算法的优越之处在于它是自适应的,确认到达的越快,数据也就发哦送的越快;而在希望减少微小分组数目的低速广域网上,则会发送更少的分组;

代码语言:javascript

复制

 if there is new data to send
      if the window size >= MSS and available data is >= MSS
        send complete MSS segment now
      else
        if there is unconfirmed data still in the pipe
          enqueue data in the buffer until an acknowledge is received
        else
          send data immediately
        end if
      end if
    end if
  1. 延迟 ACK:

如果 tcp 对每个数据包都发送一个 ack 确认,那么只是一个单独的数据包为了发送一个 ack 代价比较高,所以 tcp 会延迟一段时间,如果这段时间内有数据发送到对端,则捎带发送 ack,如果在延迟 ack 定时器触发时候,发现 ack 尚未发送,则立即单独发送;

延迟 ACK 好处:

(1) 避免糊涂窗口综合症; (2) 发送数据的时候将 ack 捎带发送,不必单独发送 ack; (3) 如果延迟时间内有多个数据段到达,那么允许协议栈发送一个 ack 确认多个报文段;

  1. 当 Nagle 遇上延迟 ACK:

试想如下典型操作,写-写-读,即通过多个写小片数据向对端发送单个逻辑的操作,两次写数据长度小于 MSS,当第一次写数据到达对端后,对端延迟 ack,不发送 ack,而本端因为要发送的数据长度小于 MSS,所以 nagle 算法起作用,数据并不会立即发送,而是等待对端发送的第一次数据确认 ack;这样的情况下,需要等待对端超时发送 ack,然后本段才能发送第二次写的数据,从而造成延迟;

  1. 关闭 Nagle 算法:

使用 TCP 套接字选项 TCP_NODELAY 可以关闭套接字选项;

如下场景考虑关闭 Nagle 算法:

(1) 对端不向本端发送数据,并且对延时比较敏感的操作;这种操作没法捎带 ack; (2) 如上写-写-读操作;对于此种情况,优先使用其他方式,而不是关闭 Nagle 算法:

TCP 和 UDP 的区别、对比

主要区别

TCP 和 UDP 的区别如 TCP 是可靠的、UDP 是不可靠的,但是实际中的表现是何为可靠?何为不可靠?具体协议的 ACK 有何区别?

不管对于 TCP 还是 UDP,都可能会被分片,这是由于以太网的 MSS 决定的;不同在于分片传输的处理:

  • UDP 而言,如果分片传输导致某些分片丢失,则接收方无法完成重组,这样发送方会将所有分片重传,如果发生重传则效率就会比较低。
    • UDP 不可靠就在于此,没有一个机制保证数据被安全送达,需要应用层去负责重传
  • TCP 而言,TCP 的分段机制可以把数据包拆小后封装在多个包里,这样就避免了被网络层分片。重传而言,TCP 只需要重传丢失的那个包而不需要重传整个包
    • TCP 可靠也在于此,TCP 会有机制保证数据被安全送达,而不需要应用层去处理重传
    • 因为 TCP 只会重传丢失的某个包而不是整个包,因此重传效率比 UDP 高很多
UDP 比 TCP 更适合语音

语音通话的场景在于不能接受延迟,但是可以接受音质稍差。这样的话,UDP 传输的时候,如果有些包丢失,应用层可以选择忽略并继续传输其他包,丢到一些包只会影响到音质,但是保证了流畅性。TCP 而言,会重传每个包,只要丢包就重传,这样就会导致有一定的延迟,在语音中如果有延迟则并不可取。

因此,TCP 和 UDP,各自有各自的适合场景。语音、视频中,UDP 更合适,像声网、linphone 等都是 UDP 去处理音视频。基础、核心协议交互中必须采用 TCP。

TCP 和 UDP 的效率问题

TCP 在传输过程都需要往返时间来确认也就是 ACK,而 UDP 则无需确认,那么 UDP 的效率一定比 TCP 高吗?这个是不一定的,虽然 UDP 可以一直往外不停的发包,不用等待 ACK;但是 TCP 有发送窗口的存在,如果发送窗口小,并没有占满带宽,那么肯定受到往返时间的约束使得效率稍低,但是如果只要窗口足够大并且合适,跑满带宽,那么 TCP 也是可以不受往返时间的约束而源源不断的传输数据。

举例:马路上只有一辆车来回跑去拉货,回程过程相当于空跑(回程相当于 TCP 的 ACK),这样 TCP 的效率当然低。但是如果在不拥塞的情况下,尽量提高车辆数量,是的马路上的车被刚好充满,这样总体的传输效率提高了,并且回程的 ACK 也不受影响。

数据包分片、MTU、MSS

数据包分片和重组

分组交换,把大的数据分割成小包,这样可以实现链路共享,而不至于因为某一方阻塞所有。既然要分割成小包,那么必然要确定一个最大的包大小,这个就是 MTU(Maximum Transmission Unit)最大传输单位,值为 1500 字节。如果除去 20 个字节的包头结构,那么一个 IP 包最大的包大小为 1500-20=1480 字节。如果要传输的数据块超过 1480 字节,那么网络层就会将其分片处理,封装为多个网络包传输。对于 TCP 而言,TCP 协议层会主动把数据分成小段后再交给网络层,TCP 的最大分段大小称之为 MSS(Maximum Segment Size),这个 MSS 被设置为 MTU 减去 IP 头和 TCP 头之后的大小,这样刚好可以满足一个 MTU。因为 UDP 没有 MSS 的概念,因此就只能交给网络层去处理分片了。

但是需要注意的是,目前有些网络是 Jumbo Frame(巨帧)或者 PPPOE 这样的设备,那么他们的 MTU 则不是 1500 字节。目前发送方并没有一个好的机制来确定最佳分片大小,应该尽量使得网络中的设备的 MTU 保持一致。如果网络中的设备的 MTU 不一致,那么 TCP 协议如何适配 MTU 呢?我们知道 TCP 建连的时候必须要先进行三次握手,TCP 在前两个握手包中会相互声明自己的 MSS。如果 client 端声明自己的 MSS=8960(巨帧),server 端申明自己的 MSS=1460,那么 client 在三次握手后就知道了 server 端的 MSS,因此当 client 想要发送大于 server 端 MSS 的包的时候就会主动将自己的 MSS 降低为 server 端的 MSS 大小,从而适配接收方的 MTU,可见,TCP 协议层做了非常多的优化和处理

既然有分片,那么接收方必然要进行分片重组,通过抓包工具可以得知,分片的每个包都包含了 off=xxx,ID=xxx 这样的信息,接收方会把 ID 相同的分片按照 off 偏移量进行重组。那么接收方又如何得知那个包才是最后的分片呢?然后什么时候开始重组呢?这里就在于最后一个分片包有一个特殊的 Flag,叫 More fragment = 0,抓包中的表现形式是 ..0…. = More fragment: Not set,这个就表示它是最后一个分片,然后可以开始重组包了。如果是其他分片包,形如 ..1…. = More fragment: set 则表示接收方需要缓存,等待其他分片传输完成

MTU 的实战

如果 client 端的 MTU=9000,server 端的 MTU=1500,那么当 client 请求 server 端的时候,client 的包经过路由器时候,要么就被丢包,要么就被分片。如果这个巨帧包在网络层携带了 DF(Don’t fragment)标志则被丢弃(设置则表示不允许分片),如果没有设置则进行分片传输。需要注意的是,这种情况下如果丢包了重传还是会被丢弃,就成了黑洞了。

测试中,可以通过 ping 命令模拟这样的情况:

代码语言:javascript

复制

成功:
ping xxx.xxx.xxx.xxx -l 1472 -f -n 1

失败:
ping xxx.xxx.xxx.xxx -l 1473 -f -n 1

-f 参数表示设置 DF 标志 -l 参数表示请求字节

当请求字节设置为1472的时候,因为ICMP头部为8字节、IP头为20字节,因此1472+8+20=1500,刚好是一个MTU,因此可以ping成功。但是第二个1473+8+20=1501字节超过MTU了,又因为设置了DF标志表示不允许分片,因此传输失败,一般这样的情况下,路由器会回复 Packet needs to be fragmented but DF set

抓包的时候,如果发现一直重传,某个某些相对较大的包(查看Len值)才重传,那么可以通过 ping xxx.xxx.xxx.xxx -l [Len] -f 值进行测试验证,通过这个 ping 指定的[Len]的大小变化来寻得规律,可能就会发现网络上某个设备的 MTU 并非 1500,这样导致了超过这个就重传的现象。

特殊的流控和带宽

client 和 server 端直接一定有交换机、路由器等设备,如果 server 端是万兆网卡,client 端是千兆网卡,就有可能使得 server 端发送过快导致数据堵在交换机上,从而交换机在堵满之后发生丢包。但是一般而言,server 端的带宽本应该要大于 client 端才算合理,为了避免拥塞,因此需要有一种流控机制,允许交换机在过载时告知 server 端放慢速度或者暂停传输。

有一种“暂停帧”,就能够满足这样的需求:当交换机的缓冲区即将被填满时发送给 server 端一个暂停帧,当 server 端等待一会儿再发,这样就可以避免溢出丢包,也避免丢包后的重传。server 端等待多久则由暂停帧中的 pause_time 指定,这样 server 端在等待 pause_time 后才会开始继续发送。当然交换机还可以给 server 端发送一个 pause_time=0 的暂停帧,告知 server 端,我已经消化完了,可以立即发送了。

注意,这的流控和 TCP 的流控是不一样的

三,用 Wireshark 分析方法论

  1. 通过 wireshark 排查问题,需要分析网络包,在网络包中寻找一些线索,然后根据网络协议作出推断,接着就是一个一个去否定,然后最终找到问题所在
  2. 需要能够理解底层 TCP 协议,要能够清楚每一个字段表示的含义
  3. 要善用 Wireshark 的一些统计、分析工具;过滤器等
  4. 发送发抓包和接收抓包是有极大区别的
  5. 要善用“三板斧“的操作流程和步骤去分析问题