【问题标题】:Measuring ping latency of a server - Python测量服务器的 ping 延迟 - Python
【发布时间】:2011-02-01 06:58:19
【问题描述】:

我有一个服务器IP地址列表,我需要检查每个服务器是否在线以及延迟是多长时间。

我还没有找到任何直接的实现方法,而且在准确计算延迟方面似乎存在一些问题。


有什么想法吗?

【问题讨论】:

标签: python networking tcp latency


【解决方案1】:

如果您已经习惯于解析字符串,您可以使用 subprocess 模块将您要查找的数据转换为字符串,如下所示:

>>> import subprocess
>>> p = subprocess.Popen(["ping.exe","www.google.com"], stdout = subprocess.PIPE)
>>> print p.communicate()[0]

Pinging www.l.google.com [209.85.225.99] with 32 bytes of data:

Reply from 209.85.225.99: bytes=32 time=59ms TTL=52
Reply from 209.85.225.99: bytes=32 time=64ms TTL=52
Reply from 209.85.225.99: bytes=32 time=104ms TTL=52
Reply from 209.85.225.99: bytes=32 time=64ms TTL=52

Ping statistics for 209.85.225.99:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 59ms, Maximum = 104ms, Average = 72ms

【讨论】:

  • 这不是一个很好的方法,因为它显然是特定于平台的(但没有必要这样做)。
  • 如果我们想将响应时间作为变量检索呢?
  • 这就是“如果你对解析感到满意”的地方......从以下内容开始:import re; timestr = re.compile("time=[0-9]+ms").findall(str(p.communicate()[0])) 并从那里改进...正则表达式模块(re)非常棒
  • >>> timestr ['time=12ms', 'time=12ms', 'time=14ms', 'time=13ms']
【解决方案2】:

按照hlovdal's suggestionfping 合作,这是我用于测试代理的解决方案。我只在Linux下试过。如果无法测量 ping 时间,则返回一个大值。用法:print get_ping_time('<ip>:<port>').

import shlex  
from subprocess import Popen, PIPE, STDOUT

def get_simple_cmd_output(cmd, stderr=STDOUT):
    """
    Execute a simple external command and get its output.
    """
    args = shlex.split(cmd)
    return Popen(args, stdout=PIPE, stderr=stderr).communicate()[0]

def get_ping_time(host):
    host = host.split(':')[0]
    cmd = "fping {host} -C 3 -q".format(host=host)
    res = [float(x) for x in get_simple_cmd_output(cmd).strip().split(':')[-1].split() if x != '-']
    if len(res) > 0:
        return sum(res) / len(res)
    else:
        return 999999

【讨论】:

  • 我认为process. 是这个sn-p 中的一个错字
  • 在超时请求之前等待多长时间?
  • 注意:在 Python 3 中需要解码 Popen 的结果:Popen(args, stdout=PIPE, stderr=stderr).communicate()[0].decode()
【解决方案3】:

如果您想避免实现所有网络通信细节,您可能会尝试在 fping 之上构建一些东西:

fping 是一个类似的程序,它使用 互联网控制消息协议 (ICMP) 回显请求以确定是否存在 目标主机正在响应。平 与 ping 的不同之处在于您可以 指定任意数量的目标 命令行,或指定文件 包含目标列表 平。而不是发送到一个目标 直到超时或回复,fping 将发送 发出一个 ping 数据包并继续 循环方式中的下一个目标。

【讨论】:

  • 谢谢,效果很好。另外我要注意“与 ping 不同,fping 是为了在脚本中使用,所以它的输出被设计成易于解析”。
  • 有没有办法手动给两个ip地址并使用fping查找它们之间的延迟?
  • 你能提供一个如何使用 fping 的例子吗?
【解决方案4】:

https://github.com/matthieu-lapeyre/network-benchmark我基于FlipperPA工作的解决方案:https://github.com/FlipperPA/latency-tester

import numpy
import pexpect


class WifiLatencyBenchmark(object):
    def __init__(self, ip):
        object.__init__(self)

        self.ip = ip
        self.interval = 0.5

        ping_command = 'ping -i ' + str(self.interval) + ' ' + self.ip
        self.ping = pexpect.spawn(ping_command)

        self.ping.timeout = 1200
        self.ping.readline()  # init
        self.wifi_latency = []
        self.wifi_timeout = 0

    def run_test(self, n_test):
        for n in range(n_test):
            p = self.ping.readline()

            try:
                ping_time = float(p[p.find('time=') + 5:p.find(' ms')])
                self.wifi_latency.append(ping_time)
                print 'test:', n + 1, '/', n_test, ', ping latency :', ping_time, 'ms'
            except:
                self.wifi_timeout = self.wifi_timeout + 1
                print 'timeout'

        self.wifi_timeout = self.wifi_timeout / float(n_test)
        self.wifi_latency = numpy.array(self.wifi_delay)

    def get_results(self):
        print 'mean latency', numpy.mean(self.wifi_latency), 'ms'
        print 'std latency', numpy.std(self.wifi_latency), 'ms'
        print 'timeout', self.wifi_timeout * 100, '%'


if __name__ == '__main__':
    ip = '192.168.0.1'
    n_test = 100

    my_wifi = WifiLatencyBenchmark(ip)

    my_wifi.run_test(n_test)
    my_wifi.get_results()

Github 存储库: https://github.com/matthieu-lapeyre/network-benchmark

【讨论】:

    【解决方案5】:

    感谢 Jabba,但该代码对我来说无法正常工作,所以我更改了类似以下的内容

    import shlex
    from subprocess import Popen, PIPE, STDOUT
    
    
    def get_simple_cmd_output(cmd, stderr=STDOUT):
        """
        Execute a simple external command and get its output.
        """
        args = shlex.split(cmd)
        return Popen(args, stdout=PIPE, stderr=stderr).communicate()[0]
    
    
    def get_ping_time(host):
        host = host.split(':')[0]
        cmd = "fping {host} -C 3 -q".format(host=host)
        # result = str(get_simple_cmd_output(cmd)).replace('\\','').split(':')[-1].split() if x != '-']
        result = str(get_simple_cmd_output(cmd)).replace('\\', '').split(':')[-1].replace("n'", '').replace("-",
                                                                                                            '').replace(
            "b''", '').split()
        res = [float(x) for x in result]
        if len(res) > 0:
            return sum(res) / len(res)
        else:
            return 999999
    
    
    def main():
        # sample hard code for test
        host = 'google.com'
        print([host, get_ping_time(host)])
    
        host = 'besparapp.com'
        print([host, get_ping_time(host)])
    
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 这适用于 Windows 吗?还是特定于 Linux 的?
    【解决方案6】:

    这篇文章有点老了,我认为今天有更好的方法。我是 python 新手,但这是我在项目中所做的:

    from pythonping import ping
    
    def ping_host(host):
        ping_result = ping(target=host, count=10, timeout=2)
    
        return {
            'host': host,
            'avg_latency': ping_result.rtt_avg_ms,
            'min_latency': ping_result.rtt_min_ms,
            'max_latency': ping_result.rtt_max_ms,
            'packet_loss': ping_result.packet_loss
        }
    
    hosts = [
        '192.168.48.1',
        '192.168.48.135'
    ]
    
    for host in hosts:
        print(ping_host(host))
    

    结果:

    {'host': '192.168.48.1', 'avg_latency': 2000.0, 'min_latency': 2000, 'max_latency': 2000, 'packet_loss': 1.0}
    {'host': '192.168.48.135', 'avg_latency': 42.67, 'min_latency': 41.71, 'max_latency': 44.17, 'packet_loss': 0.0}
    

    您可以在此处找到 pythonping 库:https://pypi.org/project/pythonping/

    【讨论】:

    • 我尝试在ping(target=host, count=10, timeout=2) 收到错误:File "/usr/local/Cellar/python@3.7/3.7.9_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 151, in __init__ _socket.socket.__init__(self, family, type, proto, fileno) PermissionError: [Errno 1] Operation not permitted 你能检查一下你的代码是否仍然运行?
    • 它仍然对我有用,我使用 python 3.9。
    • 您是否需要 root 才能运行它,正如 stackoverflow.com/questions/44252752/error-creating-raw-sockets 中所建议的那样?
    • 我在 Windows 10 上运行它,但我不是计算机的管理员。
    • 如果我以 root 身份运行,它确实可以工作。但我想避免这种情况,所以我会找到另一种方法。
    猜你喜欢
    • 2011-02-15
    • 1970-01-01
    • 2018-04-28
    • 2018-09-19
    • 2013-06-06
    • 2011-02-23
    • 2010-09-23
    • 2012-03-27
    • 2010-10-20
    相关资源
    最近更新 更多