Measuring ping latency of a server - Python

37,922

Solution 1

If you are already comfortable with parsing strings, you can use the subprocess module to get the data you are looking for into a string, like this:

>>> 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

Solution 2

Following hlovdal's suggestion to work with fping, here is my solution that I use for testing proxies. I only tried it under Linux. If no ping time could be measured, a big value is returned. Usage: 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

Solution 3

If you want to avoid implementing all the network communication details you could probably try to build something on top of fping:

fping is a like program which uses the Internet Control Message Protocol (ICMP) echo request to determine if a target host is responding. fping differs from ping in that you can specify any number of targets on the command line, or specify a file containing the lists of targets to ping. Instead of sending to one target until it times out or replies, fping will send out a ping packet and move on to the next target in a round-robin fashion.

Solution 4

https://github.com/matthieu-lapeyre/network-benchmark My solution based on the work of 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 repository: https://github.com/matthieu-lapeyre/network-benchmark

Solution 5

This post is a bit old and I think better ways exists today. I'm new to python but here's what I did on my project:

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))

Result:

{'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}

You can find the pythonping library here: https://pypi.org/project/pythonping/

Share:
37,922
RadiantHex
Author by

RadiantHex

hello! :)

Updated on July 09, 2022

Comments

  • RadiantHex
    RadiantHex almost 2 years

    I have a list of server IP addresses, I need to check if each one is online and how long the latency is.

    I haven't found any straight forward ways of implementing this, and there seems to be a few problems in calculating latency accurately.


    Any ideas?

  • Jabba
    Jabba over 11 years
    Thanks, works well. In addition I want to note that "unlike ping, fping is meant to be used in scripts, so its output is designed to be easy to parse".
  • Kat
    Kat almost 9 years
    This isn't a very good approach since it's obviously going to be platform specific (but there's no need for it to be).
  • kaptan
    kaptan over 6 years
    I think process. is a typo in this snippet
  • Prafulla Kumar Sahu
    Prafulla Kumar Sahu almost 6 years
    Is there any way to give two ip address manually and find latency between them using fping?
  • Stevoisiak
    Stevoisiak almost 5 years
    What if we want to retrieve the response time as a variable?
  • Stevoisiak
    Stevoisiak almost 5 years
    How long does this wait before timing out a request?
  • Stevoisiak
    Stevoisiak almost 5 years
    Can you provide an example of how to use fping?
  • Stevoisiak
    Stevoisiak almost 5 years
    Does this work on Windows? Or is it Linux-specific?
  • K. Brafford
    K. Brafford almost 5 years
    That's where "if you are comfortable with parsing" comes in...start with something like: import re; timestr = re.compile("time=[0-9]+ms").findall(str(p.communicate()[0])) and refine if from there...the regex module (re) is pretty awesome
  • K. Brafford
    K. Brafford almost 5 years
    >>> timestr ['time=12ms', 'time=12ms', 'time=14ms', 'time=13ms']
  • maininformer
    maininformer about 3 years
    Note: in Python 3 the result of Popen needs to be decoded: Popen(args, stdout=PIPE, stderr=stderr).communicate()[0].decode()
  • miguelmorin
    miguelmorin over 2 years
    I tried and get an error at ping(target=host, count=10, timeout=2): File "/usr/local/Cellar/[email protected]/3.7.9_2/Frameworks/Python.fram‌​ework/Versions/3.7/l‌​ib/python3.7/socket.‌​py", line 151, in __init__ _socket.socket.__init__(self, family, type, proto, fileno) PermissionError: [Errno 1] Operation not permitted Could you check that your code still runs?
  • Allan
    Allan over 2 years
    It's still working for me, I use python 3.9.
  • miguelmorin
    miguelmorin over 2 years
    Do you need to be root to run this, as suggested in stackoverflow.com/questions/44252752/error-creating-raw-sock‌​ets ?
  • Allan
    Allan over 2 years
    I am running it on Windows 10, but I am not admin of my computer.
  • miguelmorin
    miguelmorin over 2 years
    If I run as root it does work. But I'd like to avoid that, so I'll find another way.