client_closure_callback/
client_closure_callback.rs

1use rperf3::{Client, Config, ProgressEvent, Protocol};
2use std::sync::{Arc, Mutex};
3use std::time::Duration;
4
5#[tokio::main]
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7    env_logger::init();
8
9    println!("rperf3 Client with Closure Callback Example");
10    println!("===========================================\n");
11
12    // Track progress with shared state
13    let progress = Arc::new(Mutex::new(Vec::new()));
14    let progress_clone = Arc::clone(&progress);
15
16    // Configure the test
17    let config = Config::client("127.0.0.1".to_string(), 5201)
18        .with_protocol(Protocol::Tcp)
19        .with_duration(Duration::from_secs(5))
20        .with_buffer_size(128 * 1024)
21        .with_interval(Duration::from_secs(1));
22
23    // Create client with closure callback
24    let client = Client::new(config)?.with_callback(move |event: ProgressEvent| {
25        match &event {
26            ProgressEvent::TestStarted => {
27                println!("✨ Starting test...");
28            }
29            ProgressEvent::IntervalUpdate {
30                interval_end,
31                bytes,
32                bits_per_second,
33                ..
34            } => {
35                let mbps = bits_per_second / 1_000_000.0;
36                println!(
37                    "ā±ļø  {:>5.1}s | {:>10} bytes | {:>8.2} Mbps",
38                    interval_end.as_secs_f64(),
39                    bytes,
40                    mbps
41                );
42
43                // Store progress for later analysis
44                if let Ok(mut prog) = progress_clone.lock() {
45                    prog.push((*interval_end, *bytes, *bits_per_second));
46                }
47            }
48            ProgressEvent::TestCompleted {
49                total_bytes,
50                duration,
51                bits_per_second,
52                ..
53            } => {
54                println!("\nšŸŽ‰ Test finished!");
55                println!("   {} bytes in {:.2}s", total_bytes, duration.as_secs_f64());
56                println!("   Average: {:.2} Mbps", bits_per_second / 1_000_000.0);
57            }
58            ProgressEvent::Error(msg) => {
59                eprintln!("āŒ Error: {}", msg);
60            }
61        }
62    });
63
64    println!("Connecting to server at 127.0.0.1:5201...\n");
65
66    // Run the test
67    client.run().await?;
68
69    // Analyze collected progress data
70    if let Ok(prog) = progress.lock() {
71        if !prog.is_empty() {
72            println!("\nšŸ“Š Progress Analysis:");
73            let avg_mbps: f64 = prog
74                .iter()
75                .map(|(_, _, bps)| bps / 1_000_000.0)
76                .sum::<f64>()
77                / prog.len() as f64;
78            println!("   Intervals recorded: {}", prog.len());
79            println!("   Average interval speed: {:.2} Mbps", avg_mbps);
80
81            let max_mbps = prog
82                .iter()
83                .map(|(_, _, bps)| bps / 1_000_000.0)
84                .fold(0.0f64, f64::max);
85            let min_mbps = prog
86                .iter()
87                .map(|(_, _, bps)| bps / 1_000_000.0)
88                .fold(f64::INFINITY, f64::min);
89            println!("   Peak speed: {:.2} Mbps", max_mbps);
90            println!("   Lowest speed: {:.2} Mbps", min_mbps);
91        }
92    }
93
94    Ok(())
95}