【问题标题】:Is .apply_on_packets 's timeout unpredictable?.apply_on_packets 的超时时间是不可预测的吗?
【发布时间】:2026-02-01 05:45:02
【问题描述】:

以下代码在使用以下advice 时会产生不可预知的结果:

import pyshark
import pandas as pd
import asyncio

def ProcessPackets(packet):
    global packet_list
    packet_version = packet.layers[1].version
    layer_name = packet.layers[2].layer_name
    packet_list.append([packet_version, layer_name, packet.length, packet.sniff_time])

def Capture(timeOrPath):
    global packet_list
    packet_list=[]
    try:
        timeout=int(timeOrPath)
        capture = pyshark.LiveCapture()          
        capture.apply_on_packets(ProcessPackets, timeout=timeout)
    except asyncio.TimeoutError:
        pass
    except ValueError:
        capture = pyshark.FileCapture(timeOrPath)
        capture.load_packets()
        capture.apply_on_packets(ProcessPackets)
    data = pd.DataFrame(packet_list, columns=['vIP', 'protocol', 'length','timestamp']) 
    print(data['timestamp'].iloc[-1]-data['timestamp'].iloc[0])

def main(): 
    Capture(6)

if __name__ == '__main__':
    main()

有时计算的时间会超过给定的超时时间。 (timestamppacket.sniff_time

【问题讨论】:

  • 仅供参考 capture.apply_on_packets(dosomething, timeout=timeout)capture.sniff(timeout=timeout) 不应一起使用,因为它们做同样的事情。
  • @Lifeiscomplex 自发布以来我实际上已经更改了它,但这并没有帮助。我认为给定的超时包括ProcessPackets() 的处理时间,但我无法解决问题。时间是不可预测的。 incoming=data['timestamp'].iloc[-1]-data['timestamp'].iloc[0] 行给出了从文件中捕获的正确值,因此问题一定是超时
  • @Lifeiscomplex 我想它会在某个时候引发asyncio.TimeoutError,这就是捕获停止的时候。其他时候它不会超过capture.apply_on_packets(App.ProcessPackets, timeout=timeout)。虽然,其他时候我会得到超过给定超时的持续时间......
  • 你能用你正在使用的当前代码更新问题吗?另外请提供更多详细信息:incoming=data['timestamp'].iloc[-1]-data['timestamp'].iloc[0],因为我不完全理解问题。谢谢。

标签: python pyshark


【解决方案1】:

2021 年 6 月 3 日更新


在对此捕获延迟问题进行一些研究后,我确定该问题可能与 pyshark 等待 dumpcap 加载有关。 dumpcapLiveCapture 模式下加载

  def _get_dumpcap_parameters(self):
        # Don't report packet counts.
        params = ["-q"]
        if self._get_tshark_version() < LooseVersion("2.5.0"):
            # Tshark versions older than 2.5 don't support pcapng. This flag forces dumpcap to output pcap.
            params += ["-P"]
        if self.bpf_filter:
            params += ["-f", self.bpf_filter]
        if self.monitor_mode:
            params += ["-I"]
        for interface in self.interfaces:
            params += ["-i", interface]
        # Write to STDOUT
        params += ["-w", "-"]
        return params

    async def _get_tshark_process(self, packet_count=None, stdin=None):
        read, write = os.pipe()

        dumpcap_params = [get_process_path(process_name="dumpcap", tshark_path=self.tshark_path)] + self._get_dumpcap_parameters()

        self._log.debug("Creating Dumpcap subprocess with parameters: %s" % " ".join(dumpcap_params))
        dumpcap_process = await asyncio.create_subprocess_exec(*dumpcap_params, stdout=write,
                                                               stderr=self._stderr_output())
        self._created_new_process(dumpcap_params, dumpcap_process, process_name="Dumpcap")

        tshark = await super(LiveCapture, self)._get_tshark_process(packet_count=packet_count, stdin=read)
        return tshark

上面的代码在我的系统上启动它:

 /usr/local/bin/dumpcap -q -i en0 -w -

还有这个:

/usr/local/bin/tshark -l -n -T pdml -r -

我尝试将一些自定义参数传递给 LiveCapture

capture = pyshark.LiveCapture(interface='en0', custom_parameters=["-q", "--no-promiscuous-mode", "-l"])

但仍有大约 1/2 秒的延迟。

10.015577793121338
0 days 00:00:09.371264

dumpcap 文档中有一个 -a 模式,它允许持续时间超时,但我无法将该参数传递给 pyshark不会导致错误。

Tshark也有-a模式,但也会导致pyshark

内部报错
capture = pyshark.LiveCapture(interface='en0', override_prefs={'': '-r'}, custom_parameters={'': '-a duration:20'})

可能有办法在 pyshark 代码库中修改超时参数,以允许 -a 模式。为此需要进行一些测试,我目前没有时间进行。

我与 pyshark 的开发人员打开了issue on this problem

2021 年 6 月 2 日原帖


我重新编写了您的代码以将提取的项目写入 pandas 数据框。如果这不是您想要的,请根据您的确切要求更新您的问题。

import pyshark
import asyncio
import pandas as pd

packet_list = []


def process_packets(packet):
    global packet_list
    try:
        packet_version = packet.layers[1].version
        layer_name = packet.layers[2].layer_name
        packet_list.append([packet_version, layer_name, packet.length, str(packet.sniff_time)])
    except AttributeError:
        pass


def capture_packets(timeout):
    capture = pyshark.LiveCapture(interface='en0')
    try:
        capture.apply_on_packets(process_packets, timeout=timeout)
    except asyncio.TimeoutError:
        pass
    finally:
        return packet_list


def main():
    capture_packets(6)
    df = pd.DataFrame(packet_list, columns=['packet version', 'layer type', 'length', 'capture time'])
    print(df)
    # output 
          packet version layer type length                capture time
    0                 4        udp     75  2021-06-02 16:22:36.463805
    1                 4        udp     67  2021-06-02 16:22:36.517076
    2                 4        udp   1388  2021-06-02 16:22:36.706240
    3                 4        udp   1392  2021-06-02 16:22:36.706245
    4                 4        udp   1392  2021-06-02 16:22:36.706246
    truncated...


if __name__ == '__main__':
    main()

【讨论】:

  • 问题是实际捕获持续时间与给定的超时时间不同。我通过在主目录中添加这一行来检查这一点:print(df['capture time'].iloc[-1]-df['capture time'].iloc[0]) 我还将packet_list.append([packet_version, layer_name, packet.length, str(packet.sniff_time)]) 更改为packet_list.append([packet_version, layer_name, packet.length, packet.sniff_time])。对于 10 的超时,结果为 0 天 00:00:07.364705
  • 这对我的项目实际上并不重要,因为它是我学生课程的一部分,而不是实际工作。我相信这是 pyshark 的问题
  • 我通过在开头添加start = datetime.datetime.now()except asyncio.TimeoutError: print(datetime.datetime.now()-start) 来“修复”它,这给出了+-正确的结果。因此超时必须是处理时间而不是捕获持续时间
  • 哇!!数据包处理存在延迟,范围从 0.90 到 0.50 秒。这可能是一个错误,但我需要查看 python 和 pyshark 中的延迟问题。
  • 我对此进行了更多研究,发现使用 pyshark/tshark 处理数据包时存在已知延迟。此延迟可能长达一秒,因为应用程序正在执行各种操作,包括 DNS 查找。据我所知,没有办法减少这种延迟。
最近更新 更多