Client

Struct Client 

Source
pub struct Client { /* private fields */ }
Expand description

Network performance test client.

The Client is responsible for connecting to a server and running network performance tests. It supports TCP and UDP protocols, reverse mode testing, bandwidth limiting, and provides real-time progress updates through callbacks.

§Features

  • TCP and UDP: Test both reliable (TCP) and unreliable (UDP) protocols
  • Reverse Mode: Server sends data to client instead of client to server
  • Bandwidth Limiting: Control send rate with configurable bandwidth targets
  • UDP Metrics: Packet loss, jitter (RFC 3550), and out-of-order detection
  • Progress Callbacks: Real-time updates during test execution

§Examples

§Basic TCP Test

use rperf3::{Client, Config, Protocol};
use std::time::Duration;

let config = Config::client("192.168.1.100".to_string(), 5201)
    .with_protocol(Protocol::Tcp)
    .with_duration(Duration::from_secs(10));

let client = Client::new(config)?;
client.run().await?;

let measurements = client.get_measurements();
println!("Average throughput: {:.2} Mbps",
         measurements.total_bits_per_second() / 1_000_000.0);

§UDP Test with Bandwidth Limit

use rperf3::{Client, Config, Protocol};
use std::time::Duration;

let config = Config::client("192.168.1.100".to_string(), 5201)
    .with_protocol(Protocol::Udp)
    .with_bandwidth(100_000_000) // 100 Mbps
    .with_duration(Duration::from_secs(10));

let client = Client::new(config)?;
client.run().await?;

let measurements = client.get_measurements();
println!("Packets: {}, Loss: {}, Jitter: {:.3} ms",
         measurements.total_packets,
         measurements.lost_packets,
         measurements.jitter_ms);

§With Progress Callback

use rperf3::{Client, Config, ProgressEvent};
use std::time::Duration;

let config = Config::client("127.0.0.1".to_string(), 5201);

let client = Client::new(config)?
    .with_callback(|event: ProgressEvent| {
        match event {
            ProgressEvent::IntervalUpdate { bits_per_second, .. } => {
                println!("{:.2} Mbps", bits_per_second / 1_000_000.0);
            }
            _ => {}
        }
    });

client.run().await?;

Implementations§

Source§

impl Client

Source

pub fn new(config: Config) -> Result<Self>

Creates a new client with the given configuration.

§Arguments
  • config - The test configuration. Must have a server address set.
§Errors

Returns an error if the configuration doesn’t have a server address set.

§Examples
use rperf3::{Client, Config};

let config = Config::client("127.0.0.1".to_string(), 5201);
let client = Client::new(config).expect("Failed to create client");
Examples found in repository?
examples/test_json_output.rs (line 12)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::init();
7
8    let config = Config::client("127.0.0.1".to_string(), 5201)
9        .with_duration(Duration::from_secs(3))
10        .with_json(true);
11
12    let client = Client::new(config)?;
13
14    match client.run().await {
15        Ok(_) => println!("\nTest completed successfully"),
16        Err(e) => eprintln!("\nError: {}", e),
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/client.rs (line 15)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Connecting to rperf3 server at 127.0.0.1:5201...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Tcp)
12        .with_duration(Duration::from_secs(10))
13        .with_buffer_size(128 * 1024);
14
15    let client = Client::new(config)?;
16    client.run().await?;
17
18    let measurements = client.get_measurements();
19    println!(
20        "\nFinal Results: {:.2} Mbps",
21        measurements.total_bits_per_second() / 1_000_000.0
22    );
23
24    Ok(())
25}
examples/udp_client.rs (line 16)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Running UDP test with 50 Mbps target bandwidth...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Udp)
12        .with_duration(Duration::from_secs(10))
13        .with_bandwidth(50 * 1_000_000) // 50 Mbps
14        .with_buffer_size(1024);
15
16    let client = Client::new(config)?;
17    client.run().await?;
18
19    let measurements = client.get_measurements();
20    println!(
21        "\nFinal Results: {:.2} Mbps",
22        measurements.total_bits_per_second() / 1_000_000.0
23    );
24
25    Ok(())
26}
examples/client_with_callback.rs (line 63)
49async fn main() -> Result<(), Box<dyn std::error::Error>> {
50    env_logger::init();
51
52    println!("rperf3 Client with Callback Example");
53    println!("====================================\n");
54
55    // Configure the test
56    let config = Config::client("127.0.0.1".to_string(), 5201)
57        .with_protocol(Protocol::Tcp)
58        .with_duration(Duration::from_secs(10))
59        .with_buffer_size(128 * 1024)
60        .with_interval(Duration::from_secs(2)); // Report every 2 seconds
61
62    // Create client with custom callback
63    let client = Client::new(config)?.with_callback(MyProgressCallback);
64
65    println!("Connecting to server at 127.0.0.1:5201...\n");
66
67    // Run the test (callback will be invoked during execution)
68    client.run().await?;
69
70    // Get final measurements
71    let measurements = client.get_measurements();
72    println!("\n📈 Final Statistics:");
73    println!("   Total bytes: {}", measurements.total_bytes_sent);
74    println!(
75        "   Duration: {:.2}s",
76        measurements.total_duration.as_secs_f64()
77    );
78    println!(
79        "   Average bandwidth: {:.2} Mbps",
80        measurements.total_bits_per_second() / 1_000_000.0
81    );
82
83    Ok(())
84}
examples/tcp_nodelay_test.rs (line 50)
17async fn main() -> Result<(), Box<dyn std::error::Error>> {
18    // Initialize logging
19    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
20
21    println!("TCP Socket Optimization Demo");
22    println!("============================\n");
23    println!("This demo tests TCP with:");
24    println!("- TCP_NODELAY enabled (Nagle's algorithm disabled)");
25    println!("- 256KB send/receive buffers");
26    println!("- Expected 10-20% improvement over default settings\n");
27
28    // Start server in background
29    let server_config = Config::server(5201).with_protocol(Protocol::Tcp);
30    let server = Server::new(server_config);
31
32    // Run server in background task
33    tokio::spawn(async move {
34        if let Err(e) = server.run().await {
35            eprintln!("Server error: {}", e);
36        }
37    });
38
39    // Give server time to start
40    time::sleep(Duration::from_millis(100)).await;
41
42    println!("Starting TCP test (5 seconds)...\n");
43
44    // Run client test
45    let client_config = Config::client("127.0.0.1".to_string(), 5201)
46        .with_protocol(Protocol::Tcp)
47        .with_duration(Duration::from_secs(5))
48        .with_interval(Duration::from_secs(1));
49
50    let client = Client::new(client_config)?;
51    client.run().await?;
52
53    // Get measurements
54    let measurements = client.get_measurements();
55    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
56    let bits_per_second = measurements.total_bits_per_second();
57
58    println!("\n=== Results ===");
59    println!(
60        "Total transferred: {:.2} MB",
61        total_bytes as f64 / 1_000_000.0
62    );
63    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
64    println!("\nSocket optimizations applied:");
65    println!("✓ TCP_NODELAY: enabled");
66    println!("✓ Send buffer: 256KB");
67    println!("✓ Recv buffer: 256KB");
68
69    Ok(())
70}
examples/udp_buffer_test.rs (line 42)
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21    // Initialize logging
22    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
23
24    println!("UDP Socket Optimization Demo");
25    println!("============================\n");
26    println!("This demo tests UDP with:");
27    println!("- 2MB send/receive buffers");
28    println!("- Improved burst handling");
29    println!("- Expected 10-20% improvement with reduced packet loss\n");
30    println!("Note: Make sure the server is running first:");
31    println!("  cargo run --release -- -s -p 5201\n");
32
33    println!("Starting UDP test (5 seconds, 100 Mbps)...\n");
34
35    // Run client test with bandwidth limiting
36    let client_config = Config::client("127.0.0.1".to_string(), 5201)
37        .with_protocol(Protocol::Udp)
38        .with_duration(Duration::from_secs(5))
39        .with_interval(Duration::from_secs(1))
40        .with_bandwidth(100_000_000); // 100 Mbps
41
42    let client = Client::new(client_config)?;
43    client.run().await?;
44
45    // Get measurements
46    let measurements = client.get_measurements();
47    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
48    let bits_per_second = measurements.total_bits_per_second();
49    let packet_loss = if measurements.total_packets > 0 {
50        (measurements.lost_packets as f64 / measurements.total_packets as f64) * 100.0
51    } else {
52        0.0
53    };
54
55    println!("\n=== Results ===");
56    println!(
57        "Total transferred: {:.2} MB",
58        total_bytes as f64 / 1_000_000.0
59    );
60    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
61    println!("Packet loss: {:.2}%", packet_loss);
62    println!("\nSocket optimizations applied:");
63    println!("✓ Send buffer: 2MB");
64    println!("✓ Recv buffer: 2MB");
65    println!("✓ Reduced packet loss with larger buffers");
66
67    Ok(())
68}
Source

pub fn with_callback<C: ProgressCallback + 'static>(self, callback: C) -> Self

Attaches a progress callback to receive real-time test updates.

The callback will be invoked for each progress event during test execution, including test start, interval updates, completion, and errors.

§Arguments
  • callback - A function or closure that implements ProgressCallback
§Returns

Returns self for method chaining.

§Examples
use rperf3::{Client, Config, ProgressEvent};

let config = Config::client("127.0.0.1".to_string(), 5201);
let client = Client::new(config)?
    .with_callback(|event: ProgressEvent| {
        println!("Progress: {:?}", event);
    });
Examples found in repository?
examples/client_with_callback.rs (line 63)
49async fn main() -> Result<(), Box<dyn std::error::Error>> {
50    env_logger::init();
51
52    println!("rperf3 Client with Callback Example");
53    println!("====================================\n");
54
55    // Configure the test
56    let config = Config::client("127.0.0.1".to_string(), 5201)
57        .with_protocol(Protocol::Tcp)
58        .with_duration(Duration::from_secs(10))
59        .with_buffer_size(128 * 1024)
60        .with_interval(Duration::from_secs(2)); // Report every 2 seconds
61
62    // Create client with custom callback
63    let client = Client::new(config)?.with_callback(MyProgressCallback);
64
65    println!("Connecting to server at 127.0.0.1:5201...\n");
66
67    // Run the test (callback will be invoked during execution)
68    client.run().await?;
69
70    // Get final measurements
71    let measurements = client.get_measurements();
72    println!("\n📈 Final Statistics:");
73    println!("   Total bytes: {}", measurements.total_bytes_sent);
74    println!(
75        "   Duration: {:.2}s",
76        measurements.total_duration.as_secs_f64()
77    );
78    println!(
79        "   Average bandwidth: {:.2} Mbps",
80        measurements.total_bits_per_second() / 1_000_000.0
81    );
82
83    Ok(())
84}
More examples
Hide additional examples
examples/cancellable_test.rs (lines 61-91)
54async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
55    println!("Starting TCP client test (30 seconds with 5-second auto-cancel)...");
56    println!("Test will be automatically cancelled after 5 seconds.\n");
57
58    let config =
59        Config::client("127.0.0.1".to_string(), 5201).with_duration(Duration::from_secs(30)); // 30 second test
60
61    let client = Client::new(config)?.with_callback(|event: ProgressEvent| match event {
62        ProgressEvent::TestStarted => {
63            println!("Test started");
64        }
65        ProgressEvent::IntervalUpdate {
66            interval_end,
67            bits_per_second,
68            ..
69        } => {
70            println!(
71                "[{:.1}s] {:.2} Mbps",
72                interval_end.as_secs_f64(),
73                bits_per_second / 1_000_000.0
74            );
75        }
76        ProgressEvent::TestCompleted {
77            total_bytes,
78            bits_per_second,
79            ..
80        } => {
81            println!("\nTest completed:");
82            println!("  Total bytes: {}", total_bytes);
83            println!(
84                "  Average throughput: {:.2} Mbps",
85                bits_per_second / 1_000_000.0
86            );
87        }
88        ProgressEvent::Error(msg) => {
89            eprintln!("Error: {}", msg);
90        }
91    });
92
93    // Clone the cancellation token
94    let cancel_token = client.cancellation_token().clone();
95
96    // Spawn a task to cancel the test after 5 seconds
97    tokio::spawn(async move {
98        tokio::time::sleep(Duration::from_secs(5)).await;
99        println!("\n*** Cancelling test after 5 seconds ***\n");
100        cancel_token.cancel();
101    });
102
103    // Also set up CTRL+C handler for manual cancellation
104    let cancel_token_ctrl_c = client.cancellation_token().clone();
105    tokio::spawn(async move {
106        tokio::signal::ctrl_c()
107            .await
108            .expect("Failed to listen for CTRL+C");
109        println!("\nReceived CTRL+C, cancelling test...");
110        cancel_token_ctrl_c.cancel();
111    });
112
113    client.run().await?;
114    println!("Client test stopped (cancelled after ~5 seconds).");
115    Ok(())
116}
examples/test_retransmits.rs (lines 34-78)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    env_logger::init();
14
15    let args: Vec<String> = std::env::args().collect();
16    let mode = args.get(1).map(|s| s.as_str()).unwrap_or("client");
17
18    match mode {
19        "server" => {
20            println!("Starting TCP server on port 5201...");
21            println!("Retransmits will be shown if they occur during the test.\n");
22
23            let config = Config::server(5201);
24            let server = Server::new(config);
25            server.run().await?;
26        }
27        "client" => {
28            println!("Starting TCP client test (10 seconds)...");
29            println!("Retransmits will be tracked and displayed per interval.\n");
30
31            let config = Config::client("127.0.0.1".to_string(), 5201)
32                .with_duration(Duration::from_secs(10));
33
34            let client = Client::new(config)?.with_callback(|event: ProgressEvent| match event {
35                ProgressEvent::TestStarted => {
36                    println!("Test started");
37                }
38                ProgressEvent::IntervalUpdate {
39                    interval_start,
40                    interval_end,
41                    bits_per_second,
42                    retransmits,
43                    ..
44                } => {
45                    if let Some(retrans) = retransmits {
46                        println!(
47                            "[{:.1}-{:.1}s] {:.2} Mbps  - {} retransmits detected",
48                            interval_start.as_secs_f64(),
49                            interval_end.as_secs_f64(),
50                            bits_per_second / 1_000_000.0,
51                            retrans
52                        );
53                    } else {
54                        println!(
55                            "[{:.1}-{:.1}s] {:.2} Mbps  - no retransmits",
56                            interval_start.as_secs_f64(),
57                            interval_end.as_secs_f64(),
58                            bits_per_second / 1_000_000.0
59                        );
60                    }
61                }
62                ProgressEvent::TestCompleted {
63                    total_bytes,
64                    bits_per_second,
65                    ..
66                } => {
67                    println!("\nTest completed:");
68                    println!("  Total bytes: {}", total_bytes);
69                    println!(
70                        "  Average throughput: {:.2} Mbps",
71                        bits_per_second / 1_000_000.0
72                    );
73                    println!("\nNote: Retransmit tracking is only available on Linux systems.");
74                }
75                ProgressEvent::Error(msg) => {
76                    eprintln!("Error: {}", msg);
77                }
78            });
79
80            client.run().await?;
81        }
82        _ => {
83            eprintln!("Usage: {} [server|client]", args[0]);
84            std::process::exit(1);
85        }
86    }
87
88    Ok(())
89}
examples/client_closure_callback.rs (lines 24-62)
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}
Source

pub fn cancellation_token(&self) -> &CancellationToken

Returns a reference to the cancellation token.

This allows external code to cancel the running test gracefully.

§Examples
use rperf3::{Client, Config};
use std::time::Duration;

let config = Config::client("127.0.0.1".to_string(), 5201);
let client = Client::new(config)?;

// Get cancellation token to cancel from another task
let cancel_token = client.cancellation_token().clone();

tokio::spawn(async move {
    tokio::time::sleep(Duration::from_secs(5)).await;
    cancel_token.cancel();
});

client.run().await?;
Examples found in repository?
examples/cancellable_test.rs (line 94)
54async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
55    println!("Starting TCP client test (30 seconds with 5-second auto-cancel)...");
56    println!("Test will be automatically cancelled after 5 seconds.\n");
57
58    let config =
59        Config::client("127.0.0.1".to_string(), 5201).with_duration(Duration::from_secs(30)); // 30 second test
60
61    let client = Client::new(config)?.with_callback(|event: ProgressEvent| match event {
62        ProgressEvent::TestStarted => {
63            println!("Test started");
64        }
65        ProgressEvent::IntervalUpdate {
66            interval_end,
67            bits_per_second,
68            ..
69        } => {
70            println!(
71                "[{:.1}s] {:.2} Mbps",
72                interval_end.as_secs_f64(),
73                bits_per_second / 1_000_000.0
74            );
75        }
76        ProgressEvent::TestCompleted {
77            total_bytes,
78            bits_per_second,
79            ..
80        } => {
81            println!("\nTest completed:");
82            println!("  Total bytes: {}", total_bytes);
83            println!(
84                "  Average throughput: {:.2} Mbps",
85                bits_per_second / 1_000_000.0
86            );
87        }
88        ProgressEvent::Error(msg) => {
89            eprintln!("Error: {}", msg);
90        }
91    });
92
93    // Clone the cancellation token
94    let cancel_token = client.cancellation_token().clone();
95
96    // Spawn a task to cancel the test after 5 seconds
97    tokio::spawn(async move {
98        tokio::time::sleep(Duration::from_secs(5)).await;
99        println!("\n*** Cancelling test after 5 seconds ***\n");
100        cancel_token.cancel();
101    });
102
103    // Also set up CTRL+C handler for manual cancellation
104    let cancel_token_ctrl_c = client.cancellation_token().clone();
105    tokio::spawn(async move {
106        tokio::signal::ctrl_c()
107            .await
108            .expect("Failed to listen for CTRL+C");
109        println!("\nReceived CTRL+C, cancelling test...");
110        cancel_token_ctrl_c.cancel();
111    });
112
113    client.run().await?;
114    println!("Client test stopped (cancelled after ~5 seconds).");
115    Ok(())
116}
Source

pub async fn run(&self) -> Result<()>

Runs the network performance test.

This method connects to the server and executes the configured test. It will block until the test completes or an error occurs.

Progress events are emitted through the callback (if set) during execution.

§Errors

Returns an error if:

  • Cannot connect to the server
  • Network communication fails
  • Protocol errors occur
§Examples
use rperf3::{Client, Config};

let config = Config::client("127.0.0.1".to_string(), 5201);
let client = Client::new(config)?;

client.run().await?;
println!("Test completed successfully");
Examples found in repository?
examples/test_json_output.rs (line 14)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::init();
7
8    let config = Config::client("127.0.0.1".to_string(), 5201)
9        .with_duration(Duration::from_secs(3))
10        .with_json(true);
11
12    let client = Client::new(config)?;
13
14    match client.run().await {
15        Ok(_) => println!("\nTest completed successfully"),
16        Err(e) => eprintln!("\nError: {}", e),
17    }
18
19    Ok(())
20}
More examples
Hide additional examples
examples/client.rs (line 16)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Connecting to rperf3 server at 127.0.0.1:5201...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Tcp)
12        .with_duration(Duration::from_secs(10))
13        .with_buffer_size(128 * 1024);
14
15    let client = Client::new(config)?;
16    client.run().await?;
17
18    let measurements = client.get_measurements();
19    println!(
20        "\nFinal Results: {:.2} Mbps",
21        measurements.total_bits_per_second() / 1_000_000.0
22    );
23
24    Ok(())
25}
examples/udp_client.rs (line 17)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Running UDP test with 50 Mbps target bandwidth...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Udp)
12        .with_duration(Duration::from_secs(10))
13        .with_bandwidth(50 * 1_000_000) // 50 Mbps
14        .with_buffer_size(1024);
15
16    let client = Client::new(config)?;
17    client.run().await?;
18
19    let measurements = client.get_measurements();
20    println!(
21        "\nFinal Results: {:.2} Mbps",
22        measurements.total_bits_per_second() / 1_000_000.0
23    );
24
25    Ok(())
26}
examples/client_with_callback.rs (line 68)
49async fn main() -> Result<(), Box<dyn std::error::Error>> {
50    env_logger::init();
51
52    println!("rperf3 Client with Callback Example");
53    println!("====================================\n");
54
55    // Configure the test
56    let config = Config::client("127.0.0.1".to_string(), 5201)
57        .with_protocol(Protocol::Tcp)
58        .with_duration(Duration::from_secs(10))
59        .with_buffer_size(128 * 1024)
60        .with_interval(Duration::from_secs(2)); // Report every 2 seconds
61
62    // Create client with custom callback
63    let client = Client::new(config)?.with_callback(MyProgressCallback);
64
65    println!("Connecting to server at 127.0.0.1:5201...\n");
66
67    // Run the test (callback will be invoked during execution)
68    client.run().await?;
69
70    // Get final measurements
71    let measurements = client.get_measurements();
72    println!("\n📈 Final Statistics:");
73    println!("   Total bytes: {}", measurements.total_bytes_sent);
74    println!(
75        "   Duration: {:.2}s",
76        measurements.total_duration.as_secs_f64()
77    );
78    println!(
79        "   Average bandwidth: {:.2} Mbps",
80        measurements.total_bits_per_second() / 1_000_000.0
81    );
82
83    Ok(())
84}
examples/tcp_nodelay_test.rs (line 51)
17async fn main() -> Result<(), Box<dyn std::error::Error>> {
18    // Initialize logging
19    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
20
21    println!("TCP Socket Optimization Demo");
22    println!("============================\n");
23    println!("This demo tests TCP with:");
24    println!("- TCP_NODELAY enabled (Nagle's algorithm disabled)");
25    println!("- 256KB send/receive buffers");
26    println!("- Expected 10-20% improvement over default settings\n");
27
28    // Start server in background
29    let server_config = Config::server(5201).with_protocol(Protocol::Tcp);
30    let server = Server::new(server_config);
31
32    // Run server in background task
33    tokio::spawn(async move {
34        if let Err(e) = server.run().await {
35            eprintln!("Server error: {}", e);
36        }
37    });
38
39    // Give server time to start
40    time::sleep(Duration::from_millis(100)).await;
41
42    println!("Starting TCP test (5 seconds)...\n");
43
44    // Run client test
45    let client_config = Config::client("127.0.0.1".to_string(), 5201)
46        .with_protocol(Protocol::Tcp)
47        .with_duration(Duration::from_secs(5))
48        .with_interval(Duration::from_secs(1));
49
50    let client = Client::new(client_config)?;
51    client.run().await?;
52
53    // Get measurements
54    let measurements = client.get_measurements();
55    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
56    let bits_per_second = measurements.total_bits_per_second();
57
58    println!("\n=== Results ===");
59    println!(
60        "Total transferred: {:.2} MB",
61        total_bytes as f64 / 1_000_000.0
62    );
63    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
64    println!("\nSocket optimizations applied:");
65    println!("✓ TCP_NODELAY: enabled");
66    println!("✓ Send buffer: 256KB");
67    println!("✓ Recv buffer: 256KB");
68
69    Ok(())
70}
examples/udp_buffer_test.rs (line 43)
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21    // Initialize logging
22    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
23
24    println!("UDP Socket Optimization Demo");
25    println!("============================\n");
26    println!("This demo tests UDP with:");
27    println!("- 2MB send/receive buffers");
28    println!("- Improved burst handling");
29    println!("- Expected 10-20% improvement with reduced packet loss\n");
30    println!("Note: Make sure the server is running first:");
31    println!("  cargo run --release -- -s -p 5201\n");
32
33    println!("Starting UDP test (5 seconds, 100 Mbps)...\n");
34
35    // Run client test with bandwidth limiting
36    let client_config = Config::client("127.0.0.1".to_string(), 5201)
37        .with_protocol(Protocol::Udp)
38        .with_duration(Duration::from_secs(5))
39        .with_interval(Duration::from_secs(1))
40        .with_bandwidth(100_000_000); // 100 Mbps
41
42    let client = Client::new(client_config)?;
43    client.run().await?;
44
45    // Get measurements
46    let measurements = client.get_measurements();
47    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
48    let bits_per_second = measurements.total_bits_per_second();
49    let packet_loss = if measurements.total_packets > 0 {
50        (measurements.lost_packets as f64 / measurements.total_packets as f64) * 100.0
51    } else {
52        0.0
53    };
54
55    println!("\n=== Results ===");
56    println!(
57        "Total transferred: {:.2} MB",
58        total_bytes as f64 / 1_000_000.0
59    );
60    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
61    println!("Packet loss: {:.2}%", packet_loss);
62    println!("\nSocket optimizations applied:");
63    println!("✓ Send buffer: 2MB");
64    println!("✓ Recv buffer: 2MB");
65    println!("✓ Reduced packet loss with larger buffers");
66
67    Ok(())
68}
Source

pub fn get_measurements(&self) -> Measurements

Retrieves the measurements collected during the test.

This method should be called after run() completes to get the final test statistics including throughput, bytes transferred, and timing information.

§Returns

A Measurements struct containing all test statistics.

§Examples
use rperf3::{Client, Config};

let config = Config::client("127.0.0.1".to_string(), 5201);
let client = Client::new(config)?;

client.run().await?;

let measurements = client.get_measurements();
println!("Throughput: {:.2} Mbps",
         measurements.total_bits_per_second() / 1_000_000.0);
println!("Bytes transferred: {} sent, {} received",
         measurements.total_bytes_sent,
         measurements.total_bytes_received);

// UDP-specific metrics
if measurements.total_packets > 0 {
    println!("UDP Loss: {} / {} ({:.2}%)",
             measurements.lost_packets,
             measurements.total_packets,
             (measurements.lost_packets as f64 / measurements.total_packets as f64) * 100.0);
    println!("Jitter: {:.3} ms", measurements.jitter_ms);
}
§Returns

A snapshot of test measurements including:

  • Total bytes sent/received (bidirectional support)
  • Test duration and bandwidth calculations
  • Per-stream statistics
  • Interval measurements
  • UDP-specific metrics: packet count, loss percentage, jitter (RFC 3550), and out-of-order detection
Examples found in repository?
examples/client.rs (line 18)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Connecting to rperf3 server at 127.0.0.1:5201...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Tcp)
12        .with_duration(Duration::from_secs(10))
13        .with_buffer_size(128 * 1024);
14
15    let client = Client::new(config)?;
16    client.run().await?;
17
18    let measurements = client.get_measurements();
19    println!(
20        "\nFinal Results: {:.2} Mbps",
21        measurements.total_bits_per_second() / 1_000_000.0
22    );
23
24    Ok(())
25}
More examples
Hide additional examples
examples/udp_client.rs (line 19)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
7
8    println!("Running UDP test with 50 Mbps target bandwidth...");
9
10    let config = Config::client("127.0.0.1".to_string(), 5201)
11        .with_protocol(Protocol::Udp)
12        .with_duration(Duration::from_secs(10))
13        .with_bandwidth(50 * 1_000_000) // 50 Mbps
14        .with_buffer_size(1024);
15
16    let client = Client::new(config)?;
17    client.run().await?;
18
19    let measurements = client.get_measurements();
20    println!(
21        "\nFinal Results: {:.2} Mbps",
22        measurements.total_bits_per_second() / 1_000_000.0
23    );
24
25    Ok(())
26}
examples/client_with_callback.rs (line 71)
49async fn main() -> Result<(), Box<dyn std::error::Error>> {
50    env_logger::init();
51
52    println!("rperf3 Client with Callback Example");
53    println!("====================================\n");
54
55    // Configure the test
56    let config = Config::client("127.0.0.1".to_string(), 5201)
57        .with_protocol(Protocol::Tcp)
58        .with_duration(Duration::from_secs(10))
59        .with_buffer_size(128 * 1024)
60        .with_interval(Duration::from_secs(2)); // Report every 2 seconds
61
62    // Create client with custom callback
63    let client = Client::new(config)?.with_callback(MyProgressCallback);
64
65    println!("Connecting to server at 127.0.0.1:5201...\n");
66
67    // Run the test (callback will be invoked during execution)
68    client.run().await?;
69
70    // Get final measurements
71    let measurements = client.get_measurements();
72    println!("\n📈 Final Statistics:");
73    println!("   Total bytes: {}", measurements.total_bytes_sent);
74    println!(
75        "   Duration: {:.2}s",
76        measurements.total_duration.as_secs_f64()
77    );
78    println!(
79        "   Average bandwidth: {:.2} Mbps",
80        measurements.total_bits_per_second() / 1_000_000.0
81    );
82
83    Ok(())
84}
examples/tcp_nodelay_test.rs (line 54)
17async fn main() -> Result<(), Box<dyn std::error::Error>> {
18    // Initialize logging
19    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
20
21    println!("TCP Socket Optimization Demo");
22    println!("============================\n");
23    println!("This demo tests TCP with:");
24    println!("- TCP_NODELAY enabled (Nagle's algorithm disabled)");
25    println!("- 256KB send/receive buffers");
26    println!("- Expected 10-20% improvement over default settings\n");
27
28    // Start server in background
29    let server_config = Config::server(5201).with_protocol(Protocol::Tcp);
30    let server = Server::new(server_config);
31
32    // Run server in background task
33    tokio::spawn(async move {
34        if let Err(e) = server.run().await {
35            eprintln!("Server error: {}", e);
36        }
37    });
38
39    // Give server time to start
40    time::sleep(Duration::from_millis(100)).await;
41
42    println!("Starting TCP test (5 seconds)...\n");
43
44    // Run client test
45    let client_config = Config::client("127.0.0.1".to_string(), 5201)
46        .with_protocol(Protocol::Tcp)
47        .with_duration(Duration::from_secs(5))
48        .with_interval(Duration::from_secs(1));
49
50    let client = Client::new(client_config)?;
51    client.run().await?;
52
53    // Get measurements
54    let measurements = client.get_measurements();
55    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
56    let bits_per_second = measurements.total_bits_per_second();
57
58    println!("\n=== Results ===");
59    println!(
60        "Total transferred: {:.2} MB",
61        total_bytes as f64 / 1_000_000.0
62    );
63    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
64    println!("\nSocket optimizations applied:");
65    println!("✓ TCP_NODELAY: enabled");
66    println!("✓ Send buffer: 256KB");
67    println!("✓ Recv buffer: 256KB");
68
69    Ok(())
70}
examples/udp_buffer_test.rs (line 46)
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21    // Initialize logging
22    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
23
24    println!("UDP Socket Optimization Demo");
25    println!("============================\n");
26    println!("This demo tests UDP with:");
27    println!("- 2MB send/receive buffers");
28    println!("- Improved burst handling");
29    println!("- Expected 10-20% improvement with reduced packet loss\n");
30    println!("Note: Make sure the server is running first:");
31    println!("  cargo run --release -- -s -p 5201\n");
32
33    println!("Starting UDP test (5 seconds, 100 Mbps)...\n");
34
35    // Run client test with bandwidth limiting
36    let client_config = Config::client("127.0.0.1".to_string(), 5201)
37        .with_protocol(Protocol::Udp)
38        .with_duration(Duration::from_secs(5))
39        .with_interval(Duration::from_secs(1))
40        .with_bandwidth(100_000_000); // 100 Mbps
41
42    let client = Client::new(client_config)?;
43    client.run().await?;
44
45    // Get measurements
46    let measurements = client.get_measurements();
47    let total_bytes = measurements.total_bytes_sent + measurements.total_bytes_received;
48    let bits_per_second = measurements.total_bits_per_second();
49    let packet_loss = if measurements.total_packets > 0 {
50        (measurements.lost_packets as f64 / measurements.total_packets as f64) * 100.0
51    } else {
52        0.0
53    };
54
55    println!("\n=== Results ===");
56    println!(
57        "Total transferred: {:.2} MB",
58        total_bytes as f64 / 1_000_000.0
59    );
60    println!("Throughput: {:.2} Mbps", bits_per_second / 1_000_000.0);
61    println!("Packet loss: {:.2}%", packet_loss);
62    println!("\nSocket optimizations applied:");
63    println!("✓ Send buffer: 2MB");
64    println!("✓ Recv buffer: 2MB");
65    println!("✓ Reduced packet loss with larger buffers");
66
67    Ok(())
68}

Auto Trait Implementations§

§

impl Freeze for Client

§

impl !RefUnwindSafe for Client

§

impl Send for Client

§

impl Sync for Client

§

impl Unpin for Client

§

impl !UnwindSafe for Client

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V