zpinger
Async, protocol-agnostic latency probe library. Every protocol
implements the same Pinger trait — call ping().await and get
real round-trip time across the application layer, not just whether
a TCP socket opens.
Powers the knockknock CLI;
also usable directly from any Rust async application.
Supported protocols
| Struct | Schemes | Measures |
|---|---|---|
TcpPinger |
host:port |
TCP connect + 1-byte probe + read |
UdpPinger |
host:port |
UDP send + recv from ephemeral local socket |
HttpPinger |
http://, https:// |
Full HTTP/1.1 request + status-line validation |
WebSocketPinger |
ws://, wss:// |
RFC 6455 upgrade + control PING/PONG round trip |
DnsPinger |
host or host:port (default port 53) | UDP query + response validation (ID / QR / RCODE / question echo) |
MqttPinger |
mqtt://, mqtts:// (3.1.1 default; v5 opt-in) |
CONNECT/CONNACK + PINGREQ/PINGRESP + DISCONNECT |
GrpcPinger |
grpc:// / http:// plaintext, grpcs:// / https:// TLS |
grpc.health.v1.Health/Check unary RPC |
TLS for https:// / wss:// / mqtts:// / grpcs:// is handled by
rustls with the Mozilla root CA
bundle from
webpki-roots — pure Rust,
no system trust store dependency.
Install
[]
= "0.4"
= { = "1", = ["rt-multi-thread", "macros"] }
zpinger requires a tokio runtime — the Pinger trait is async, so
your application needs to be async too. Any tokio runtime works
(current-thread or multi-thread).
Quick start
use Duration;
use ;
async
The Pinger trait
Ok(()) means the protocol-level exchange completed; Err carries
the underlying I/O or protocol error. Use zpinger::timed(pinger)
for the elapsed time of a single ping. The trait is object-safe via
async-trait, so
Box<dyn Pinger> works for heterogeneous dispatch.
Per-protocol examples
TCP
use ;
let p = new;
p.ping.await?;
UDP
use ;
let p = new;
p.ping.await?;
HTTP / HTTPS
use ;
// Plain HTTP GET
new
.ping
.await?;
// HTTPS POST — TLS handled automatically via the scheme
new
.ping
.await?;
WebSocket / WSS
use ;
// ws:// runs the RFC 6455 upgrade + a control PING/PONG round trip
new
.ping
.await?;
// wss:// reuses the rustls + webpki-roots TLS stack
new
.ping
.await?;
DNS
use ;
new
.with_record_type
.ping
.await?;
MQTT (3.1.1 default, MQTT 5 opt-in)
use ;
// Plain mqtt:// (default port 1883), MQTT 3.1.1
new
.ping
.await?;
// mqtts:// (default port 8883) with MQTT 5 + custom client id
new
.with_client_id
.with_version
.ping
.await?;
gRPC
Calls the standard
gRPC Health Checking Protocol
grpc.health.v1.Health/Check unary RPC. Reports success when the
server returns SERVING.
use ;
// Plaintext H2C
new
.ping
.await?;
// TLS via webpki-roots default trust
new
.with_service
.ping
.await?;
Heterogeneous dispatch via Box<dyn Pinger>
use Duration;
use ;
let pingers: = vec!;
for p in &pingers
TLS configuration
Every TLS-aware pinger (HttpPinger, WebSocketPinger,
MqttPinger, GrpcPinger) ships with a sensible default that
trusts public CAs via webpki-roots. For self-signed test
endpoints, inject a custom config:
use Arc;
use ;
// Build whatever rustls ClientConfig you like — e.g. a custom
// trust anchor for a self-signed test endpoint.
let config: = build_my_test_config;
new
.with_tls_config
.ping
.await?;
GrpcPinger uses with_ca_cert(pem_bytes) instead — tonic's TLS
config takes a different shape.
Timeouts
Every pinger struct has .with_timeout(Duration). The default is 5
seconds. The whole ping() call respects the timeout (not just
each I/O op individually) — if your handshake stalls halfway, you
still get the timeout error.
use Duration;
use ;
new
.with_timeout
.ping
.await?;
Resolve helper
For showing what the pinger will actually connect to (the CLI uses
this for the DNS lookup: ... banner):
let addrs = resolve.await;
// ↑ defaults to port 443 because of the https scheme.
resolve returns an empty Vec on failure rather than panicking —
the actual pinger surfaces the real error when you call it.
CLI + MCP
If you want to use the same probes from a shell or from an AI agent
without writing Rust, install the
knockknock CLI. It also
ships an optional knockknock-mcp Model Context Protocol server
behind the mcp feature.
License
MIT — same as knockknock. See LICENSE.