#udp #python #networking #udp-networking #ping

udp_pinger

A library for pinging devices using unprivileged UDP packets

2 unstable releases

Uses new Rust 2024

0.2.0 Oct 12, 2025
0.1.0 Oct 10, 2025

#13 in #udp-networking

Apache-2.0

44KB
874 lines

UDP Pinger

An implementation of a UDP-based ping utility. This library does not require root privileges, unlike ICMP-based ping utilities.

Usage

Rust Example

use std::{net::Ipv4Addr, time::Duration};

use udp_pinger;

fn main() {
    let mut p = udp_pinger::Pinger::try_new(Ipv4Addr::new(10, 23, 16, 11)).unwrap();
    p.ping(Duration::from_secs(1)).unwrap();
    p.start_periodic(Duration::from_millis(500), Duration::from_millis(350))
        .unwrap();
    for _ in 0..4 {
        let opt_sample = p.wait_for_sample(Duration::from_secs(2));
        if let Ok(sample) = opt_sample {
            println!("Sample: {}", sample);
        } else {
            panic!("No sample received in 2 second, exiting.");
        }
    }
    p.stop_periodic();
    assert!(p.is_reachable(2).unwrap());
    println!("Latency: {:?}", p.latency_ema(0.1).unwrap());
    println!("{}", p.stats());
}

Rust Async Example

use std::{net::Ipv4Addr, time::Duration};

use udp_pinger;

async fn main() {
    // works on any runtime, use smol here for simplicity
    let p = udp_pinger::AsyncPinger::try_new(Ipv4Addr::new(10, 23, 16, 11)).await.unwrap();
    p.ping(Duration::from_secs(1)).await.unwrap();
    {
        let ex = smol::Executor::new();
        ex.spawn(p.periodic(Duration::from_millis(500), Duration::from_millis(350)))
            .detach();
        let poller = async {
            for _ in 0..4 {
                let opt_sample = p.wait_for_sample(Duration::from_secs(2)).await;
                if let Ok(sample) = opt_sample {
                    println!("Sample: {}", sample);
                } else {
                    panic!("No sample received in 2 second, exiting.");
                }
            }
        };
        ex.run(poller).await;
    }
    assert!(p.is_reachable(2).unwrap());
    println!("Latency: {:?}", p.latency_ema(0.1).unwrap());
    println!("{}", p.stats());
}

Python Bindings

from udp_pinger import Pinger

def main() -> None:
    p = Pinger("10.23.15.11")
    p.ping(timeout_secs=1.0)
    p.start_periodic(interval_secs=0.5, per_ping_timeout_secs=0.35)
    for _ in range(4):
        sample = p.wait_for_sample(timeout_secs=2.0)
        if sample is not None:
            print(f"Sample: {sample}")
        else:
            raise RuntimeError("No sample received in 2 second, exiting.")
    p.stop_periodic()
    assert p.is_reachable(2) is True
    print(f"Latency: {p.latency_ms()} ms")
    print(p.stats())

Features

  • py: Enables Python bindings using PyO3.
  • async: Enables asynchronous support using generic async primitives.
  • alternate_port: Uses an alternate UDP port (33434) for sending packets instead of the default (59999).

License

This project is licensed under the Apache License 2.0. See the LICENSE file for details.

Dependencies

~0.6–6MB
~137K SLoC