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
impl Client
Sourcepub fn new(config: Config) -> Result<Self>
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?
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
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}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}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}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}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}Sourcepub fn with_callback<C: ProgressCallback + 'static>(self, callback: C) -> Self
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 implementsProgressCallback
§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?
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
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}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}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}Sourcepub fn cancellation_token(&self) -> &CancellationToken
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?
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}Sourcepub async fn run(&self) -> Result<()>
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?
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
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}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}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}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}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}Sourcepub fn get_measurements(&self) -> Measurements
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?
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
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}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}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}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}