54 lines
1.8 KiB
JavaScript
Executable file
54 lines
1.8 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/** UDP echo RTT. server: node udp-probe.mjs server [port]
|
|
* client: node udp-probe.mjs client <host> <count> [port] [size] */
|
|
import dgram from "node:dgram";
|
|
|
|
const mode = process.argv[2] || "server";
|
|
const port = Number(process.argv[mode === "server" ? 3 : 5] || 9999);
|
|
|
|
if (mode === "server") {
|
|
const s = dgram.createSocket("udp4");
|
|
s.on("message", (msg, rinfo) => s.send(msg, rinfo.port, rinfo.address));
|
|
s.bind(port, "0.0.0.0", () => console.log(JSON.stringify({ mode: "udp-server", port })));
|
|
} else {
|
|
const host = process.argv[3];
|
|
const count = Number(process.argv[4] || 1000);
|
|
const size = Number(process.argv[6] || 128);
|
|
const sock = dgram.createSocket("udp4");
|
|
const payload = Buffer.alloc(size, 7);
|
|
const samples = [];
|
|
let i = 0;
|
|
const sendOne = () => {
|
|
const t0 = process.hrtime.bigint();
|
|
const once = (msg) => {
|
|
sock.off("message", once);
|
|
samples.push(Number(process.hrtime.bigint() - t0) / 1000);
|
|
i += 1;
|
|
if (i >= count) {
|
|
samples.sort((a, b) => a - b);
|
|
const us = (n) => `${(n / 1000).toFixed(3)}ms`;
|
|
const pct = (p) => samples[Math.min(samples.length - 1, Math.floor((p / 100) * samples.length))];
|
|
const sum = samples.reduce((a, b) => a + b, 0);
|
|
console.log(
|
|
JSON.stringify({
|
|
mode: "udp-ping",
|
|
count: samples.length,
|
|
size,
|
|
host,
|
|
min: us(samples[0]),
|
|
avg: us(sum / samples.length),
|
|
p50: us(pct(50)),
|
|
p99: us(pct(99)),
|
|
max: us(samples[samples.length - 1]),
|
|
p50_us: Math.round(pct(50)),
|
|
p99_us: Math.round(pct(99)),
|
|
}),
|
|
);
|
|
sock.close();
|
|
} else sendOne();
|
|
};
|
|
sock.on("message", once);
|
|
sock.send(payload, port, host);
|
|
};
|
|
sendOne();
|
|
}
|