Archive

Posts Tagged ‘ping’

force requests to use IPv4

June 28, 2019 Leave a comment

Problem
I have a script that periodically calls the API of a server to fetch some data. It worked well under Manjaro and Ubuntu. However, after a system update, the script stopped working on Ubuntu.

Diagnosis
It turned out that requests.get() couldn’t connect to the server. I tried to ping the host and under Ubuntu ping resolved an IPv6 address and it was unreachable. You can force ping to use IPv4 with the “-4” switch (ex.: “ping example.com -4“). Under Manjaro ping resolved an IPv4 address by default and the Python script worked well. Under Ubuntu, however, requests.get() wanted to use IPv6 and for some reason the given host was not reachable through that protocol.

Solution
In my Python code I used the following patch to force the usage of IPv4. requests relies on a lower level library, urllib3, thus the urllib3 part had to be patched:

import socket
import requests.packages.urllib3.util.connection as urllib3_cn

def allowed_gai_family():
    family = socket.AF_INET    # force IPv4
    return family

urllib3_cn.allowed_gai_family = allowed_gai_family

It solved the issue under Ubuntu. This tip is from here.

Categories: python Tags: , , , , ,

Measuring ping latency of a server

December 27, 2012 Leave a comment

Problem
You have a list of servers (e.g. proxies) and you want to choose the fastest one. How to measure the ping latencies?

Solution
There is a nice Unix command for this called “fping” (sudo apt-get install fping). “Unlike ping, fping is meant to be used in scripts, so its output is designed to be easy to parse.

Example:

$ fping 221.130.199.121 -C 3 -q
221.130.199.121 : 389.08 411.15 411.82

It sends 3 packets and after the colon it prints each response time. If a response time could not be measured then you will see a “-” in its place.

In Python, here is my solution:

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 process.get_simple_cmd_output(cmd).strip().split(':')[-1].split() if x != '-']
    if len(res) > 0:
        return sum(res) / len(res)
    else:
        return 999999

It calculates the average of the response times. If no response time could be measured then it returns a big value.

I sent this solution to SO too.