Scapy如何获取ping时间?

12

我正在尝试编写一个能够计算ping延迟平均值的scapy脚本,所以我需要获取ICMP echo/reply包发送和接收之间的时间。目前我有以下代码:

#! /usr/bin/env python
from scapy.all import *
from time import *

def QoS_ping(host, count=3):
  packet = Ether()/IP(dst=host)/ICMP()
  t=0.0
  for x in range(count):
      t1=time()
      ans=srp(packet,iface="eth0", verbose=0)
      t2=time()
      t+=t2-t1
  return (t/count)*1000

问题在于使用 time() 函数并不能得到一个好的结果。例如,在一个域名上我发现用 time() 函数得到的时间是 134 毫秒,而使用 ping 系统函数在同一域名上我得到的是 30 毫秒(当然是平均值)。

我的问题是:有没有一种方法可以通过 scapy 得到发送数据包和接收数据包之间的确切时间间隔?我不想使用 popen() 函数或其他系统调用,因为我需要 scapy 来管理未来的数据包。


你使用 time.clock() 可能会更加幸运,而不是使用 time.time() - Nathan Villaescusa
使用 srp1 可能会比 srp 更有效。 - Nathan Villaescusa
Nathan,你在scapy中做的任何事情都非常慢... scapy在Python中解析整个数据包(在用户空间中)。 它无法与使用OS系统调用的C实现竞争。 - Mike Pennington
将其作为答案添加,不要在问题中回答你的问题。 - Mike Pennington
1
纯Python中的ping请参考以下链接:https://github.com/jedie/python-ping/blob/master/ping.py - jfs
3个回答

8
有没有一种方法可以通过scapy获取发送数据包和接收数据包之间的准确时间差?您可以使用pak.timepak.sent_time。我修改了您的脚本来使用它们...
import statistics
import os

from scapy.all import Ether, IP, ICMP, srp

if os.geteuid() > 0:
    raise OSError("This script must run as root")

ping_rtt_list = list()
def ping_addr(host, count=3):
    packet = Ether()/IP(dst=host)/ICMP()
    t=0.0
    for x in range(count):
        x += 1  # Start with x = 1 (not zero)
        ans, unans = srp(packet, iface="eth0", filter='icmp', verbose=0)
        rx = ans[0][1]
        tx = ans[0][0]
        delta = rx.time - tx.sent_time
        print("ping #{0} rtt: {1} second".format(x, round(delta, 6)))
        ping_rtt_list.append(round(delta, 6))
    return ping_rtt_list

if __name__=="__main__":
    ping_rtt_list = ping_addr('172.16.15.1')
    rtt_avg = round(statistics.mean(ping_rtt_list), 6)
    print("Avg ping rtt (seconds):", rtt_avg)

一个示例运行:
$ sudo /opt/virtual_env/py37_test/bin/python ./ping_w_scapy.py
ping #1 rtt: 0.002019 second
ping #2 rtt: 0.002347 second
ping #3 rtt: 0.001807 second
Avg ping rtt (seconds): 0.002058

285.5毫秒 + 230.9毫秒 + 219.9毫秒的平均值为245毫秒;单个数据包的响应时间以秒为单位打印,并在return期间将平均值转换为毫秒。 - Mike Pennington
未来读者注意:使用 rx.time-tx.sent_time 可能会导致负时间测量(scapy 2.4.0-2.4.3rc1)。我已经为任何感兴趣的人创建了一个问题(#1952)。 - Felix ZY

0

Mike,为了得到平均时间,只需要进行一个小修复,修改:

print "Average %0.3f" % float(match.group(1))

to:

 print "Average %0.3f" % float(match.group(2))

因为(match.group(1))将获取最小时间而不是平均时间,如所述。


0

顺便说一下,使用非缓冲的Python(使用python -u启动)可以提高时间精度,因为Python不会等待缓冲区决定何时转储。使用您上面的脚本,它将我的结果从偏差0.4毫秒改变为偏差0.1左右。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接