concurrency/
concurrency.rs1use rust_raknet::{RaknetSocket, Reliability};
3use std::{
4 error::Error,
5 sync::Arc,
6 time::{Duration, Instant},
7};
8use tokio::{sync::Semaphore, task::JoinSet};
9
10#[tokio::main(worker_threads = 4)]
11async fn main() -> Result<(), Box<dyn Error>> {
12 let args: Vec<_> = std::env::args().collect();
13 let address = args
14 .get(1)
15 .ok_or("usage: concurrency ADDRESS [CONNECTIONS] [MESSAGES]")?
16 .parse()?;
17 let connections: usize = args.get(2).map_or(Ok(512), |n| n.parse())?;
18 let messages: usize = args.get(3).map_or(Ok(100), |n| n.parse())?;
19 if connections == 0 || messages == 0 {
20 return Err("counts must be positive".into());
21 }
22 tokio::time::timeout(Duration::from_secs(120), async {
23 let started = Instant::now();
24 let dialing = Arc::new(Semaphore::new(8));
25 let mut tasks = JoinSet::new();
26 for index in 0..connections {
27 let dialing = dialing.clone();
28 tasks.spawn(async move {
29 let _permit = dialing.acquire().await.unwrap();
30 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
31 Ok::<_, rust_raknet::error::RaknetError>((index, socket))
32 });
33 }
34 let mut sockets = Vec::with_capacity(connections);
35 while let Some(result) = tasks.join_next().await { sockets.push(result??); }
36 let handshake_seconds = started.elapsed().as_secs_f64();
37 let transfer = Instant::now();
38 let mut exchanges = JoinSet::new();
39 for (index, socket) in sockets {
40 exchanges.spawn(async move {
41 fn payload(connection: usize, message: usize) -> Vec<u8> {
42 let size = [64, 800, 4096][message % 3];
43 let mut bytes = vec![0xfe; size];
44 bytes[1..9].copy_from_slice(&(connection as u64).to_le_bytes());
45 bytes[9..17].copy_from_slice(&(message as u64).to_le_bytes());
46 bytes
47 }
48 let sender = async {
49 for message in 0..messages {
50 socket.send(&payload(index, message), Reliability::ReliableOrdered).await?;
51 }
52 socket.flush().await
53 };
54 let receiver = async {
55 tokio::time::sleep(Duration::from_millis(30)).await;
57 for message in 0..messages {
58 let actual = socket.recv().await?;
59 if actual != payload(index, message) {
60 return Err(rust_raknet::error::RaknetError::PacketParseError);
61 }
62 }
63 Ok(())
64 };
65 tokio::try_join!(sender, receiver)?;
66 socket.close().await
67 });
68 }
69 while let Some(result) = exchanges.join_next().await { result??; }
70 println!("PASS: {connections} simultaneous connections, {} unique ordered echoes; handshake={handshake_seconds:.3}s, transfer={:.3}s", connections * messages, transfer.elapsed().as_secs_f64());
71 Ok::<_, Box<dyn Error>>(())
72 }).await?
73}