pub struct RaknetSocket { /* private fields */ }Expand description
A RakNet connection backed by a UDP socket.
Implementations§
Source§impl RaknetSocket
impl RaknetSocket
Sourcepub fn set_idle_maintenance(&self, enabled: bool)
pub fn set_idle_maintenance(&self, enabled: bool)
Pause maintenance after 500 ms of quiet traffic and empty queues.
Disabled by default to preserve the periodic schedule under load. This can save CPU with many idle peers, but changes maintenance timing. Sending or receiving work wakes a paused connection. Disabling this option immediately resumes periodic maintenance.
Sourcepub async fn from(
addr: &SocketAddr,
s: &Arc<UdpSocket>,
receiver: Receiver<Vec<u8>>,
mtu: u16,
collecter: Arc<Mutex<Sender<SocketAddr>>>,
raknet_version: u8,
) -> Self
pub async fn from( addr: &SocketAddr, s: &Arc<UdpSocket>, receiver: Receiver<Vec<u8>>, mtu: u16, collecter: Arc<Mutex<Sender<SocketAddr>>>, raknet_version: u8, ) -> Self
Create a RakNet socket for an established UDP connection.
This constructor is used internally by [RaknetListener].
Sourcepub async fn connect(addr: &SocketAddr) -> Result<Self>
pub async fn connect(addr: &SocketAddr) -> Result<Self>
Sourcepub async fn connect_with_version(
addr: &SocketAddr,
raknet_version: u8,
) -> Result<Self>
pub async fn connect_with_version( addr: &SocketAddr, raknet_version: u8, ) -> Result<Self>
Examples found in repository?
270 async fn connect(address: std::net::SocketAddr, tcp: bool) -> Result<Self, BenchError> {
271 if tcp {
272 let stream = TcpStream::connect(address).await?;
273 stream.set_nodelay(true)?;
274 Ok(Self::Tcp {
275 stream,
276 record: Vec::new(),
277 })
278 } else {
279 Ok(Self::RakNet(
280 RaknetSocket::connect_with_version(&address, 11).await?,
281 ))
282 }
283 }More examples
4async fn main() {
5 let args: Vec<_> = env::args().collect();
6 let address = args[1].parse().unwrap();
7 let version: u8 = args[2].parse().unwrap();
8 rust_raknet::enable_raknet_log(3);
9 println!("TARGET {address} RAKNET {version}");
10 let socket = match tokio::time::timeout(
11 Duration::from_secs(10),
12 RaknetSocket::connect_with_version(&address, version),
13 )
14 .await
15 {
16 Ok(Ok(socket)) => {
17 println!("HANDSHAKE OK");
18 socket
19 }
20 Ok(Err(error)) => {
21 println!("HANDSHAKE ERROR {error}");
22 std::process::exit(1);
23 }
24 Err(_) => {
25 println!("HANDSHAKE TIMEOUT");
26 std::process::exit(2);
27 }
28 };
29 if let Some(protocol) = args.get(3) {
30 let protocol: i32 = protocol.parse().unwrap();
31 let mut request = vec![0xfe, 6, 0xc1, 1];
32 request.extend_from_slice(&protocol.to_be_bytes());
33 socket
34 .send(&request, Reliability::ReliableOrdered)
35 .await
36 .unwrap();
37 println!("SENT RequestNetworkSettings protocol={protocol}");
38 match tokio::time::timeout(Duration::from_secs(5), socket.recv()).await {
39 Ok(Ok(data)) => {
40 println!(
41 "RECEIVED {} bytes: {:02x?}",
42 data.len(),
43 &data[..data.len().min(80)]
44 );
45 if data.len() >= 8 && data[0] == 0xfe && data[2..4] == [0x8f, 1] {
46 println!(
47 "NETWORK_SETTINGS OK threshold={} algorithm={}",
48 u16::from_le_bytes([data[4], data[5]]),
49 u16::from_le_bytes([data[6], data[7]])
50 );
51 } else {
52 println!("UNEXPECTED APPLICATION RESPONSE");
53 std::process::exit(3);
54 }
55 }
56 other => {
57 println!("APPLICATION RECEIVE ERROR {other:?}");
58 std::process::exit(4);
59 }
60 }
61 }
62 let _ = tokio::time::timeout(Duration::from_secs(1), socket.close()).await;
63}6async fn main() -> Result<(), Box<dyn Error>> {
7 if std::env::var_os("RAKNET_DEBUG").is_some() {
8 rust_raknet::enable_raknet_log(7);
9 }
10 let address = std::env::args()
11 .nth(1)
12 .ok_or("missing peer address")?
13 .parse()?;
14 let batch = std::env::args().nth(2).as_deref() == Some("--batch");
15 tokio::time::timeout(Duration::from_secs(60), async {
16 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
17 let mut count = 0;
18 for size in [64, 800, 4096, 10000] {
19 if batch && size <= 800 {
20 for first in (0..100).step_by(16) {
21 let messages: Vec<_> = (first..(first + 16).min(100))
22 .map(|index| {
23 let mut message: Vec<_> =
24 (0..size).map(|i| (i + index) as u8).collect();
25 message[0] = 0xfe;
26 rust_raknet::Bytes::from(message)
27 })
28 .collect();
29 socket
30 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
31 .await?;
32 for expected in messages {
33 assert_eq!(
34 socket.recv().await?.as_slice(),
35 expected.as_ref(),
36 "message reordered, duplicated or corrupted"
37 );
38 count += 1;
39 }
40 }
41 } else {
42 for index in 0..100 {
43 let mut payload: Vec<_> = (0..size).map(|i| (i + index) as u8).collect();
44 payload[0] = 0xfe;
45 socket.send(&payload, Reliability::ReliableOrdered).await?;
46 assert_eq!(
47 socket.recv().await?,
48 payload,
49 "message reordered, duplicated or corrupted"
50 );
51 count += 1;
52 }
53 }
54 }
55 socket.close().await?;
56 println!("PASS: {count} unique ordered messages, 64/800/4096/10000 bytes");
57 Ok::<_, Box<dyn Error>>(())
58 })
59 .await?
60}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 // Exercise a slow application without blocking protocol ACKs.
56 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}Sourcepub async fn connect_with_version_and_mtu(
addr: &SocketAddr,
raknet_version: u8,
requested_mtu: u16,
) -> Result<Self>
pub async fn connect_with_version_and_mtu( addr: &SocketAddr, raknet_version: u8, requested_mtu: u16, ) -> Result<Self>
Connect with an explicit RakNet version and nominal MTU in bytes.
The requested MTU must be between 61 and 1,492 bytes. The server may negotiate a smaller value. Choose a size the network path can carry; the ordinary connection APIs retain their 1,400-byte default.
Sourcepub async fn close(&self) -> Result<()>
pub async fn close(&self) -> Result<()>
Close the RakNet connection. The connection also closes when the socket is dropped. This method is idempotent.
§Example
let (latency, motd) = socket::RaknetSocket::ping("127.0.0.1:19132".parse().unwrap()).await.unwrap();
assert!((0..10).contains(&latency));Examples found in repository?
4async fn main() {
5 let args: Vec<_> = env::args().collect();
6 let address = args[1].parse().unwrap();
7 let version: u8 = args[2].parse().unwrap();
8 rust_raknet::enable_raknet_log(3);
9 println!("TARGET {address} RAKNET {version}");
10 let socket = match tokio::time::timeout(
11 Duration::from_secs(10),
12 RaknetSocket::connect_with_version(&address, version),
13 )
14 .await
15 {
16 Ok(Ok(socket)) => {
17 println!("HANDSHAKE OK");
18 socket
19 }
20 Ok(Err(error)) => {
21 println!("HANDSHAKE ERROR {error}");
22 std::process::exit(1);
23 }
24 Err(_) => {
25 println!("HANDSHAKE TIMEOUT");
26 std::process::exit(2);
27 }
28 };
29 if let Some(protocol) = args.get(3) {
30 let protocol: i32 = protocol.parse().unwrap();
31 let mut request = vec![0xfe, 6, 0xc1, 1];
32 request.extend_from_slice(&protocol.to_be_bytes());
33 socket
34 .send(&request, Reliability::ReliableOrdered)
35 .await
36 .unwrap();
37 println!("SENT RequestNetworkSettings protocol={protocol}");
38 match tokio::time::timeout(Duration::from_secs(5), socket.recv()).await {
39 Ok(Ok(data)) => {
40 println!(
41 "RECEIVED {} bytes: {:02x?}",
42 data.len(),
43 &data[..data.len().min(80)]
44 );
45 if data.len() >= 8 && data[0] == 0xfe && data[2..4] == [0x8f, 1] {
46 println!(
47 "NETWORK_SETTINGS OK threshold={} algorithm={}",
48 u16::from_le_bytes([data[4], data[5]]),
49 u16::from_le_bytes([data[6], data[7]])
50 );
51 } else {
52 println!("UNEXPECTED APPLICATION RESPONSE");
53 std::process::exit(3);
54 }
55 }
56 other => {
57 println!("APPLICATION RECEIVE ERROR {other:?}");
58 std::process::exit(4);
59 }
60 }
61 }
62 let _ = tokio::time::timeout(Duration::from_secs(1), socket.close()).await;
63}More examples
6async fn main() -> Result<(), Box<dyn Error>> {
7 if std::env::var_os("RAKNET_DEBUG").is_some() {
8 rust_raknet::enable_raknet_log(7);
9 }
10 let address = std::env::args()
11 .nth(1)
12 .ok_or("missing peer address")?
13 .parse()?;
14 let batch = std::env::args().nth(2).as_deref() == Some("--batch");
15 tokio::time::timeout(Duration::from_secs(60), async {
16 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
17 let mut count = 0;
18 for size in [64, 800, 4096, 10000] {
19 if batch && size <= 800 {
20 for first in (0..100).step_by(16) {
21 let messages: Vec<_> = (first..(first + 16).min(100))
22 .map(|index| {
23 let mut message: Vec<_> =
24 (0..size).map(|i| (i + index) as u8).collect();
25 message[0] = 0xfe;
26 rust_raknet::Bytes::from(message)
27 })
28 .collect();
29 socket
30 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
31 .await?;
32 for expected in messages {
33 assert_eq!(
34 socket.recv().await?.as_slice(),
35 expected.as_ref(),
36 "message reordered, duplicated or corrupted"
37 );
38 count += 1;
39 }
40 }
41 } else {
42 for index in 0..100 {
43 let mut payload: Vec<_> = (0..size).map(|i| (i + index) as u8).collect();
44 payload[0] = 0xfe;
45 socket.send(&payload, Reliability::ReliableOrdered).await?;
46 assert_eq!(
47 socket.recv().await?,
48 payload,
49 "message reordered, duplicated or corrupted"
50 );
51 count += 1;
52 }
53 }
54 }
55 socket.close().await?;
56 println!("PASS: {count} unique ordered messages, 64/800/4096/10000 bytes");
57 Ok::<_, Box<dyn Error>>(())
58 })
59 .await?
60}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 // Exercise a slow application without blocking protocol ACKs.
56 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}Sourcepub async fn send(&self, buf: &[u8], reliability: Reliability) -> Result<()>
pub async fn send(&self, buf: &[u8], reliability: Reliability) -> Result<()>
Send a Bedrock game packet.
The packet must begin with 0xfe. ReliableOrdered messages are fragmented
when necessary; other modes must fit the negotiated MTU. Messages exceeding
65,536 fragments or the 64 MiB send budget (including fragment overhead) return
RaknetError::PacketSizeExceedMTU. A full send queue applies asynchronous
backpressure until capacity is available or the connection closes.
§Example
let socket = RaknetSocket::connect("127.0.0.1:19132".parse().unwrap()).await.unwrap();
socket.send(&[0xfe], Reliability::ReliableOrdered).await.unwrap();Examples found in repository?
285 async fn send(&mut self, payload: &[u8]) -> Result<(), BenchError> {
286 match self {
287 Self::RakNet(socket) => socket.send(payload, Reliability::ReliableOrdered).await?,
288 Self::Tcp { stream, record, .. } => {
289 let length = u32::try_from(payload.len())?;
290 record.clear();
291 record.extend_from_slice(&length.to_le_bytes());
292 record.extend_from_slice(payload);
293 stream.write_all(record).await?;
294 }
295 }
296 Ok(())
297 }More examples
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5 use rust_raknet::{RaknetListener, Reliability};
6 let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7 let count = std::env::args()
8 .nth(2)
9 .unwrap_or_else(|| "4".into())
10 .parse()?;
11 let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12 let mut batch_messages = false;
13 for option in std::env::args().skip(3) {
14 listener = match option.as_str() {
15 "--receive-batching" => listener.with_receive_batching(true),
16 "--idle-maintenance" => listener.with_idle_maintenance(true),
17 "--batch-messages" => {
18 batch_messages = true;
19 listener
20 }
21 _ => return Err(format!("unknown option: {option}").into()),
22 };
23 }
24 listener.listen().await;
25 println!("Sharded echo listening on {}", listener.local_addr()?);
26 loop {
27 let client = listener.accept().await?;
28 if batch_messages {
29 tokio::spawn(async move {
30 let mut messages = Vec::with_capacity(16);
31 while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32 if client
33 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34 .await
35 .is_err()
36 {
37 break;
38 }
39 if messages.len() == 16 {
40 tokio::task::yield_now().await;
41 }
42 }
43 });
44 } else {
45 tokio::spawn(async move {
46 while let Ok(payload) = client.recv().await {
47 if client
48 .send(&payload, Reliability::ReliableOrdered)
49 .await
50 .is_err()
51 {
52 break;
53 }
54 }
55 });
56 }
57 }
58}4async fn main() {
5 let args: Vec<_> = env::args().collect();
6 let address = args[1].parse().unwrap();
7 let version: u8 = args[2].parse().unwrap();
8 rust_raknet::enable_raknet_log(3);
9 println!("TARGET {address} RAKNET {version}");
10 let socket = match tokio::time::timeout(
11 Duration::from_secs(10),
12 RaknetSocket::connect_with_version(&address, version),
13 )
14 .await
15 {
16 Ok(Ok(socket)) => {
17 println!("HANDSHAKE OK");
18 socket
19 }
20 Ok(Err(error)) => {
21 println!("HANDSHAKE ERROR {error}");
22 std::process::exit(1);
23 }
24 Err(_) => {
25 println!("HANDSHAKE TIMEOUT");
26 std::process::exit(2);
27 }
28 };
29 if let Some(protocol) = args.get(3) {
30 let protocol: i32 = protocol.parse().unwrap();
31 let mut request = vec![0xfe, 6, 0xc1, 1];
32 request.extend_from_slice(&protocol.to_be_bytes());
33 socket
34 .send(&request, Reliability::ReliableOrdered)
35 .await
36 .unwrap();
37 println!("SENT RequestNetworkSettings protocol={protocol}");
38 match tokio::time::timeout(Duration::from_secs(5), socket.recv()).await {
39 Ok(Ok(data)) => {
40 println!(
41 "RECEIVED {} bytes: {:02x?}",
42 data.len(),
43 &data[..data.len().min(80)]
44 );
45 if data.len() >= 8 && data[0] == 0xfe && data[2..4] == [0x8f, 1] {
46 println!(
47 "NETWORK_SETTINGS OK threshold={} algorithm={}",
48 u16::from_le_bytes([data[4], data[5]]),
49 u16::from_le_bytes([data[6], data[7]])
50 );
51 } else {
52 println!("UNEXPECTED APPLICATION RESPONSE");
53 std::process::exit(3);
54 }
55 }
56 other => {
57 println!("APPLICATION RECEIVE ERROR {other:?}");
58 std::process::exit(4);
59 }
60 }
61 }
62 let _ = tokio::time::timeout(Duration::from_secs(1), socket.close()).await;
63}6async fn main() -> Result<(), Box<dyn Error>> {
7 if std::env::var_os("RAKNET_DEBUG").is_some() {
8 rust_raknet::enable_raknet_log(7);
9 }
10 let address = std::env::args()
11 .nth(1)
12 .ok_or("missing peer address")?
13 .parse()?;
14 let batch = std::env::args().nth(2).as_deref() == Some("--batch");
15 tokio::time::timeout(Duration::from_secs(60), async {
16 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
17 let mut count = 0;
18 for size in [64, 800, 4096, 10000] {
19 if batch && size <= 800 {
20 for first in (0..100).step_by(16) {
21 let messages: Vec<_> = (first..(first + 16).min(100))
22 .map(|index| {
23 let mut message: Vec<_> =
24 (0..size).map(|i| (i + index) as u8).collect();
25 message[0] = 0xfe;
26 rust_raknet::Bytes::from(message)
27 })
28 .collect();
29 socket
30 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
31 .await?;
32 for expected in messages {
33 assert_eq!(
34 socket.recv().await?.as_slice(),
35 expected.as_ref(),
36 "message reordered, duplicated or corrupted"
37 );
38 count += 1;
39 }
40 }
41 } else {
42 for index in 0..100 {
43 let mut payload: Vec<_> = (0..size).map(|i| (i + index) as u8).collect();
44 payload[0] = 0xfe;
45 socket.send(&payload, Reliability::ReliableOrdered).await?;
46 assert_eq!(
47 socket.recv().await?,
48 payload,
49 "message reordered, duplicated or corrupted"
50 );
51 count += 1;
52 }
53 }
54 }
55 socket.close().await?;
56 println!("PASS: {count} unique ordered messages, 64/800/4096/10000 bytes");
57 Ok::<_, Box<dyn Error>>(())
58 })
59 .await?
60}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 // Exercise a slow application without blocking protocol ACKs.
56 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}Sourcepub async fn send_with_order_channel(
&self,
buf: &[u8],
reliability: Reliability,
order_channel: u8,
) -> Result<()>
pub async fn send_with_order_channel( &self, buf: &[u8], reliability: Reliability, order_channel: u8, ) -> Result<()>
Send a packet on a specific RakNet ordering channel.
Each ordering channel has an independent reliable-ordered sequence. The channel is relevant to ordered and sequenced reliability modes; unordered modes do not carry an ordering channel on the wire.
Sourcepub async fn send_bytes(
&self,
data: Bytes,
reliability: Reliability,
) -> Result<()>
pub async fn send_bytes( &self, data: Bytes, reliability: Reliability, ) -> Result<()>
Send an owned, immutable payload without copying it into the retry queue.
Sourcepub async fn send_bytes_with_order_channel(
&self,
data: Bytes,
reliability: Reliability,
order_channel: u8,
) -> Result<()>
pub async fn send_bytes_with_order_channel( &self, data: Bytes, reliability: Reliability, order_channel: u8, ) -> Result<()>
Send an owned payload on a RakNet ordering channel.
Sourcepub async fn send_batch(
&self,
messages: &[&[u8]],
reliability: Reliability,
) -> Result<()>
pub async fn send_batch( &self, messages: &[&[u8]], reliability: Reliability, ) -> Result<()>
Send an already available batch without waiting to collect more messages.
Small ReliableOrdered messages can share standard RakNet frame sets up to the negotiated MTU. Loss feedback or a retransmission timeout restores individual sends for this connection. Other modes retain individual datagrams. A batch is validated before sending any member. Cancellation can send a prefix; already queued reliable messages continue delivery. Empty batches are a no-op.
Sourcepub async fn send_batch_with_order_channel(
&self,
messages: &[&[u8]],
reliability: Reliability,
order_channel: u8,
) -> Result<()>
pub async fn send_batch_with_order_channel( &self, messages: &[&[u8]], reliability: Reliability, order_channel: u8, ) -> Result<()>
Send a borrowed batch on one ordering channel.
Sourcepub async fn send_bytes_batch(
&self,
messages: &[Bytes],
reliability: Reliability,
) -> Result<()>
pub async fn send_bytes_batch( &self, messages: &[Bytes], reliability: Reliability, ) -> Result<()>
Send owned buffers without copying their payload into the retry queue.
Examples found in repository?
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5 use rust_raknet::{RaknetListener, Reliability};
6 let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7 let count = std::env::args()
8 .nth(2)
9 .unwrap_or_else(|| "4".into())
10 .parse()?;
11 let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12 let mut batch_messages = false;
13 for option in std::env::args().skip(3) {
14 listener = match option.as_str() {
15 "--receive-batching" => listener.with_receive_batching(true),
16 "--idle-maintenance" => listener.with_idle_maintenance(true),
17 "--batch-messages" => {
18 batch_messages = true;
19 listener
20 }
21 _ => return Err(format!("unknown option: {option}").into()),
22 };
23 }
24 listener.listen().await;
25 println!("Sharded echo listening on {}", listener.local_addr()?);
26 loop {
27 let client = listener.accept().await?;
28 if batch_messages {
29 tokio::spawn(async move {
30 let mut messages = Vec::with_capacity(16);
31 while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32 if client
33 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34 .await
35 .is_err()
36 {
37 break;
38 }
39 if messages.len() == 16 {
40 tokio::task::yield_now().await;
41 }
42 }
43 });
44 } else {
45 tokio::spawn(async move {
46 while let Ok(payload) = client.recv().await {
47 if client
48 .send(&payload, Reliability::ReliableOrdered)
49 .await
50 .is_err()
51 {
52 break;
53 }
54 }
55 });
56 }
57 }
58}More examples
6async fn main() -> Result<(), Box<dyn Error>> {
7 if std::env::var_os("RAKNET_DEBUG").is_some() {
8 rust_raknet::enable_raknet_log(7);
9 }
10 let address = std::env::args()
11 .nth(1)
12 .ok_or("missing peer address")?
13 .parse()?;
14 let batch = std::env::args().nth(2).as_deref() == Some("--batch");
15 tokio::time::timeout(Duration::from_secs(60), async {
16 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
17 let mut count = 0;
18 for size in [64, 800, 4096, 10000] {
19 if batch && size <= 800 {
20 for first in (0..100).step_by(16) {
21 let messages: Vec<_> = (first..(first + 16).min(100))
22 .map(|index| {
23 let mut message: Vec<_> =
24 (0..size).map(|i| (i + index) as u8).collect();
25 message[0] = 0xfe;
26 rust_raknet::Bytes::from(message)
27 })
28 .collect();
29 socket
30 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
31 .await?;
32 for expected in messages {
33 assert_eq!(
34 socket.recv().await?.as_slice(),
35 expected.as_ref(),
36 "message reordered, duplicated or corrupted"
37 );
38 count += 1;
39 }
40 }
41 } else {
42 for index in 0..100 {
43 let mut payload: Vec<_> = (0..size).map(|i| (i + index) as u8).collect();
44 payload[0] = 0xfe;
45 socket.send(&payload, Reliability::ReliableOrdered).await?;
46 assert_eq!(
47 socket.recv().await?,
48 payload,
49 "message reordered, duplicated or corrupted"
50 );
51 count += 1;
52 }
53 }
54 }
55 socket.close().await?;
56 println!("PASS: {count} unique ordered messages, 64/800/4096/10000 bytes");
57 Ok::<_, Box<dyn Error>>(())
58 })
59 .await?
60}79async fn run<const LOADED: bool>(
80 address: std::net::SocketAddr,
81 count: usize,
82 messages: usize,
83 size: usize,
84 tcp: bool,
85 batch: bool,
86) -> Result<(), BenchError> {
87 println!(
88 "Sending API: {}",
89 if tcp {
90 "TCP complete-record writes"
91 } else if batch {
92 "send_bytes_batch (ready messages only)"
93 } else {
94 "send (no batch API)"
95 }
96 );
97 let setup = Instant::now();
98 let dialing = Arc::new(Semaphore::new(8));
99 let mut tasks = JoinSet::new();
100 for id in 0..count {
101 let dialing = dialing.clone();
102 tasks.spawn(async move {
103 let _permit = dialing.acquire().await.unwrap();
104 let socket = EchoConnection::connect(address, tcp).await?;
105 Ok::<_, BenchError>((id, socket))
106 });
107 }
108 let mut sockets = Vec::with_capacity(count);
109 while let Some(result) = tasks.join_next().await {
110 sockets.push(result??);
111 }
112 let setup_seconds = setup.elapsed().as_secs_f64();
113 let barrier = Arc::new(Barrier::new(count + 1));
114 let start_gate = Arc::new(Barrier::new(count + 1));
115 let mut exchanges = JoinSet::new();
116 for (id, mut socket) in sockets {
117 let barrier = barrier.clone();
118 let start_gate = start_gate.clone();
119 exchanges.spawn(async move {
120 let mut rtts = Vec::with_capacity(if LOADED { messages.max(20) } else { 20 });
121 let mut stamps = if LOADED {
122 vec![Instant::now(); 16]
123 } else {
124 Vec::new()
125 };
126 let mut expected = payload(id, 0, size);
127 let mut outgoing = expected.clone();
128 let mut actual = Vec::with_capacity(size);
129 for message in 0..20 {
130 expected[9..17].copy_from_slice(&(message as u64).to_le_bytes());
131 let start = Instant::now();
132 socket.send(&expected).await?;
133 socket.recv(size, &mut actual).await?;
134 if actual != expected {
135 return Err::<_, BenchError>("echo payload or order mismatch".into());
136 }
137 rtts.push(start.elapsed().as_nanos());
138 }
139 if LOADED {
140 rtts.clear();
141 }
142 barrier.wait().await;
143 start_gate.wait().await;
144 // Match the C reference's sliding application window. Refill a slot
145 // as each echo arrives instead of waiting for a whole batch.
146 if batch {
147 let EchoConnection::RakNet(ref connection) = socket else {
148 unreachable!()
149 };
150 let mut sent = 0;
151 let mut received = 0;
152 let mut incoming = Vec::with_capacity(16);
153 let mut pending = Vec::with_capacity(16);
154 for message in 0..messages.min(16) {
155 pending.push(rust_raknet::Bytes::from(payload(id, message + 20, size)));
156 if LOADED {
157 stamps[message % 16] = Instant::now();
158 }
159 sent += 1;
160 }
161 connection
162 .send_bytes_batch(&pending, Reliability::ReliableOrdered)
163 .await?;
164 while received < messages {
165 connection.recv_bytes_batch(&mut incoming, 16).await?;
166 for actual in &incoming {
167 expected[9..17].copy_from_slice(&((received + 20) as u64).to_le_bytes());
168 if actual.as_ref() != expected {
169 return Err::<_, BenchError>("echo payload or order mismatch".into());
170 }
171 if LOADED {
172 rtts.push(stamps[received % 16].elapsed().as_nanos());
173 }
174 received += 1;
175 }
176 pending.clear();
177 for _ in 0..incoming.len().min(messages - sent) {
178 pending.push(rust_raknet::Bytes::from(payload(id, sent + 20, size)));
179 if LOADED {
180 stamps[sent % 16] = Instant::now();
181 }
182 sent += 1;
183 }
184 if !pending.is_empty() {
185 connection
186 .send_bytes_batch(&pending, Reliability::ReliableOrdered)
187 .await?;
188 }
189 }
190 } else {
191 let mut sent = 0;
192 while sent < messages.min(16) {
193 outgoing[9..17].copy_from_slice(&((sent + 20) as u64).to_le_bytes());
194 if LOADED {
195 stamps[sent % 16] = Instant::now();
196 }
197 socket.send(&outgoing).await?;
198 sent += 1;
199 }
200 for received in 0..messages {
201 expected[9..17].copy_from_slice(&((received + 20) as u64).to_le_bytes());
202 socket.recv(size, &mut actual).await?;
203 if actual != expected {
204 return Err::<_, BenchError>("echo payload or order mismatch".into());
205 }
206 if LOADED {
207 rtts.push(stamps[received % 16].elapsed().as_nanos());
208 }
209 if sent < messages {
210 outgoing[9..17].copy_from_slice(&((sent + 20) as u64).to_le_bytes());
211 if LOADED {
212 stamps[sent % 16] = Instant::now();
213 }
214 socket.send(&outgoing).await?;
215 sent += 1;
216 }
217 }
218 }
219 // Keep every connection open until all peers finish the measured burst.
220 Ok::<_, BenchError>((socket, rtts))
221 });
222 }
223 barrier.wait().await;
224 let started = Instant::now();
225 start_gate.wait().await;
226 let mut retained = Vec::with_capacity(count);
227 let mut rtts = Vec::with_capacity(count * if LOADED { messages } else { 20 });
228 while let Some(result) = exchanges.join_next().await {
229 let (socket, values) = result??;
230 retained.push(socket);
231 rtts.extend(values);
232 }
233 let elapsed = started.elapsed().as_secs_f64();
234 println!("RTT samples: {}", rtts.len());
235 rtts.sort_unstable();
236 println!(
237 "Connections: {count}\nMessages per connection: {messages}\nPayload size: {size} bytes\nSetup: {setup_seconds:.6} s\nElapsed: {elapsed:.6} s"
238 );
239 println!(
240 "Echo payload throughput (per direction): {:.2} MiB/s",
241 count as f64 * messages as f64 * size as f64 / 1048576.0 / elapsed
242 );
243 println!(
244 "RTT p50: {:.1} us\nRTT p95: {:.1} us\nRTT p99: {:.1} us",
245 percentile(&rtts, 50),
246 percentile(&rtts, 95),
247 percentile(&rtts, 99)
248 );
249 println!(
250 "RTT measurement: {}",
251 if LOADED {
252 "per-message throughout measured burst"
253 } else {
254 "sequential warmup before burst"
255 }
256 );
257 println!("Verified ordered echoes: {}", count * (messages + 20));
258 drop(retained);
259 Ok(())
260}Sourcepub async fn send_bytes_batch_with_order_channel(
&self,
messages: &[Bytes],
reliability: Reliability,
order_channel: u8,
) -> Result<()>
pub async fn send_bytes_batch_with_order_channel( &self, messages: &[Bytes], reliability: Reliability, order_channel: u8, ) -> Result<()>
Send an owned batch on one ordering channel.
Sourcepub async fn flush(&self) -> Result<()>
pub async fn flush(&self) -> Result<()>
Wait until all reliable packets have been acknowledged.
§Example
let socket = RaknetSocket::connect("127.0.0.1:19132".parse().unwrap()).await.unwrap();
socket.send(&[0xfe], Reliability::ReliableOrdered).await.unwrap();
socket.flush().await.unwrap();Examples found in repository?
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 // Exercise a slow application without blocking protocol ACKs.
56 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}Sourcepub async fn recv(&self) -> Result<Vec<u8>>
pub async fn recv(&self) -> Result<Vec<u8>>
Receive the next game packet.
§Example
let socket = RaknetSocket::connect("127.0.0.1:19132".parse().unwrap()).await.unwrap();
let buf = socket.recv().await.unwrap();
if buf[0] == 0xfe{
//do something
}Examples found in repository?
299 async fn recv(&mut self, size: usize, incoming: &mut Vec<u8>) -> Result<(), BenchError> {
300 match self {
301 Self::RakNet(socket) => *incoming = socket.recv().await?,
302 Self::Tcp { stream, .. } => {
303 let length = stream.read_u32_le().await? as usize;
304 if length != size {
305 return Err("unexpected TCP record length".into());
306 }
307 incoming.resize(length, 0);
308 stream.read_exact(incoming).await?;
309 }
310 }
311 Ok(())
312 }More examples
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5 use rust_raknet::{RaknetListener, Reliability};
6 let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7 let count = std::env::args()
8 .nth(2)
9 .unwrap_or_else(|| "4".into())
10 .parse()?;
11 let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12 let mut batch_messages = false;
13 for option in std::env::args().skip(3) {
14 listener = match option.as_str() {
15 "--receive-batching" => listener.with_receive_batching(true),
16 "--idle-maintenance" => listener.with_idle_maintenance(true),
17 "--batch-messages" => {
18 batch_messages = true;
19 listener
20 }
21 _ => return Err(format!("unknown option: {option}").into()),
22 };
23 }
24 listener.listen().await;
25 println!("Sharded echo listening on {}", listener.local_addr()?);
26 loop {
27 let client = listener.accept().await?;
28 if batch_messages {
29 tokio::spawn(async move {
30 let mut messages = Vec::with_capacity(16);
31 while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32 if client
33 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34 .await
35 .is_err()
36 {
37 break;
38 }
39 if messages.len() == 16 {
40 tokio::task::yield_now().await;
41 }
42 }
43 });
44 } else {
45 tokio::spawn(async move {
46 while let Ok(payload) = client.recv().await {
47 if client
48 .send(&payload, Reliability::ReliableOrdered)
49 .await
50 .is_err()
51 {
52 break;
53 }
54 }
55 });
56 }
57 }
58}4async fn main() {
5 let args: Vec<_> = env::args().collect();
6 let address = args[1].parse().unwrap();
7 let version: u8 = args[2].parse().unwrap();
8 rust_raknet::enable_raknet_log(3);
9 println!("TARGET {address} RAKNET {version}");
10 let socket = match tokio::time::timeout(
11 Duration::from_secs(10),
12 RaknetSocket::connect_with_version(&address, version),
13 )
14 .await
15 {
16 Ok(Ok(socket)) => {
17 println!("HANDSHAKE OK");
18 socket
19 }
20 Ok(Err(error)) => {
21 println!("HANDSHAKE ERROR {error}");
22 std::process::exit(1);
23 }
24 Err(_) => {
25 println!("HANDSHAKE TIMEOUT");
26 std::process::exit(2);
27 }
28 };
29 if let Some(protocol) = args.get(3) {
30 let protocol: i32 = protocol.parse().unwrap();
31 let mut request = vec![0xfe, 6, 0xc1, 1];
32 request.extend_from_slice(&protocol.to_be_bytes());
33 socket
34 .send(&request, Reliability::ReliableOrdered)
35 .await
36 .unwrap();
37 println!("SENT RequestNetworkSettings protocol={protocol}");
38 match tokio::time::timeout(Duration::from_secs(5), socket.recv()).await {
39 Ok(Ok(data)) => {
40 println!(
41 "RECEIVED {} bytes: {:02x?}",
42 data.len(),
43 &data[..data.len().min(80)]
44 );
45 if data.len() >= 8 && data[0] == 0xfe && data[2..4] == [0x8f, 1] {
46 println!(
47 "NETWORK_SETTINGS OK threshold={} algorithm={}",
48 u16::from_le_bytes([data[4], data[5]]),
49 u16::from_le_bytes([data[6], data[7]])
50 );
51 } else {
52 println!("UNEXPECTED APPLICATION RESPONSE");
53 std::process::exit(3);
54 }
55 }
56 other => {
57 println!("APPLICATION RECEIVE ERROR {other:?}");
58 std::process::exit(4);
59 }
60 }
61 }
62 let _ = tokio::time::timeout(Duration::from_secs(1), socket.close()).await;
63}6async fn main() -> Result<(), Box<dyn Error>> {
7 if std::env::var_os("RAKNET_DEBUG").is_some() {
8 rust_raknet::enable_raknet_log(7);
9 }
10 let address = std::env::args()
11 .nth(1)
12 .ok_or("missing peer address")?
13 .parse()?;
14 let batch = std::env::args().nth(2).as_deref() == Some("--batch");
15 tokio::time::timeout(Duration::from_secs(60), async {
16 let socket = RaknetSocket::connect_with_version(&address, 11).await?;
17 let mut count = 0;
18 for size in [64, 800, 4096, 10000] {
19 if batch && size <= 800 {
20 for first in (0..100).step_by(16) {
21 let messages: Vec<_> = (first..(first + 16).min(100))
22 .map(|index| {
23 let mut message: Vec<_> =
24 (0..size).map(|i| (i + index) as u8).collect();
25 message[0] = 0xfe;
26 rust_raknet::Bytes::from(message)
27 })
28 .collect();
29 socket
30 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
31 .await?;
32 for expected in messages {
33 assert_eq!(
34 socket.recv().await?.as_slice(),
35 expected.as_ref(),
36 "message reordered, duplicated or corrupted"
37 );
38 count += 1;
39 }
40 }
41 } else {
42 for index in 0..100 {
43 let mut payload: Vec<_> = (0..size).map(|i| (i + index) as u8).collect();
44 payload[0] = 0xfe;
45 socket.send(&payload, Reliability::ReliableOrdered).await?;
46 assert_eq!(
47 socket.recv().await?,
48 payload,
49 "message reordered, duplicated or corrupted"
50 );
51 count += 1;
52 }
53 }
54 }
55 socket.close().await?;
56 println!("PASS: {count} unique ordered messages, 64/800/4096/10000 bytes");
57 Ok::<_, Box<dyn Error>>(())
58 })
59 .await?
60}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 // Exercise a slow application without blocking protocol ACKs.
56 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}Sourcepub async fn recv_bytes(&self) -> Result<Bytes>
pub async fn recv_bytes(&self) -> Result<Bytes>
Receive a game payload as an immutable buffer that can be forwarded with
send_bytes without copying its application bytes.
Sourcepub async fn recv_batch(
&self,
output: &mut Vec<Vec<u8>>,
limit: usize,
) -> Result<usize>
pub async fn recv_batch( &self, output: &mut Vec<Vec<u8>>, limit: usize, ) -> Result<usize>
Receive one message, then drain up to limit messages already available.
Clears output and never waits to fill a batch. Work is capped at 64
messages per call; a zero limit returns immediately.
Sourcepub async fn recv_bytes_batch(
&self,
output: &mut Vec<Bytes>,
limit: usize,
) -> Result<usize>
pub async fn recv_bytes_batch( &self, output: &mut Vec<Bytes>, limit: usize, ) -> Result<usize>
Receive an immediately available batch for forwarding with send_bytes_batch.
Examples found in repository?
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5 use rust_raknet::{RaknetListener, Reliability};
6 let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7 let count = std::env::args()
8 .nth(2)
9 .unwrap_or_else(|| "4".into())
10 .parse()?;
11 let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12 let mut batch_messages = false;
13 for option in std::env::args().skip(3) {
14 listener = match option.as_str() {
15 "--receive-batching" => listener.with_receive_batching(true),
16 "--idle-maintenance" => listener.with_idle_maintenance(true),
17 "--batch-messages" => {
18 batch_messages = true;
19 listener
20 }
21 _ => return Err(format!("unknown option: {option}").into()),
22 };
23 }
24 listener.listen().await;
25 println!("Sharded echo listening on {}", listener.local_addr()?);
26 loop {
27 let client = listener.accept().await?;
28 if batch_messages {
29 tokio::spawn(async move {
30 let mut messages = Vec::with_capacity(16);
31 while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32 if client
33 .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34 .await
35 .is_err()
36 {
37 break;
38 }
39 if messages.len() == 16 {
40 tokio::task::yield_now().await;
41 }
42 }
43 });
44 } else {
45 tokio::spawn(async move {
46 while let Ok(payload) = client.recv().await {
47 if client
48 .send(&payload, Reliability::ReliableOrdered)
49 .await
50 .is_err()
51 {
52 break;
53 }
54 }
55 });
56 }
57 }
58}More examples
79async fn run<const LOADED: bool>(
80 address: std::net::SocketAddr,
81 count: usize,
82 messages: usize,
83 size: usize,
84 tcp: bool,
85 batch: bool,
86) -> Result<(), BenchError> {
87 println!(
88 "Sending API: {}",
89 if tcp {
90 "TCP complete-record writes"
91 } else if batch {
92 "send_bytes_batch (ready messages only)"
93 } else {
94 "send (no batch API)"
95 }
96 );
97 let setup = Instant::now();
98 let dialing = Arc::new(Semaphore::new(8));
99 let mut tasks = JoinSet::new();
100 for id in 0..count {
101 let dialing = dialing.clone();
102 tasks.spawn(async move {
103 let _permit = dialing.acquire().await.unwrap();
104 let socket = EchoConnection::connect(address, tcp).await?;
105 Ok::<_, BenchError>((id, socket))
106 });
107 }
108 let mut sockets = Vec::with_capacity(count);
109 while let Some(result) = tasks.join_next().await {
110 sockets.push(result??);
111 }
112 let setup_seconds = setup.elapsed().as_secs_f64();
113 let barrier = Arc::new(Barrier::new(count + 1));
114 let start_gate = Arc::new(Barrier::new(count + 1));
115 let mut exchanges = JoinSet::new();
116 for (id, mut socket) in sockets {
117 let barrier = barrier.clone();
118 let start_gate = start_gate.clone();
119 exchanges.spawn(async move {
120 let mut rtts = Vec::with_capacity(if LOADED { messages.max(20) } else { 20 });
121 let mut stamps = if LOADED {
122 vec![Instant::now(); 16]
123 } else {
124 Vec::new()
125 };
126 let mut expected = payload(id, 0, size);
127 let mut outgoing = expected.clone();
128 let mut actual = Vec::with_capacity(size);
129 for message in 0..20 {
130 expected[9..17].copy_from_slice(&(message as u64).to_le_bytes());
131 let start = Instant::now();
132 socket.send(&expected).await?;
133 socket.recv(size, &mut actual).await?;
134 if actual != expected {
135 return Err::<_, BenchError>("echo payload or order mismatch".into());
136 }
137 rtts.push(start.elapsed().as_nanos());
138 }
139 if LOADED {
140 rtts.clear();
141 }
142 barrier.wait().await;
143 start_gate.wait().await;
144 // Match the C reference's sliding application window. Refill a slot
145 // as each echo arrives instead of waiting for a whole batch.
146 if batch {
147 let EchoConnection::RakNet(ref connection) = socket else {
148 unreachable!()
149 };
150 let mut sent = 0;
151 let mut received = 0;
152 let mut incoming = Vec::with_capacity(16);
153 let mut pending = Vec::with_capacity(16);
154 for message in 0..messages.min(16) {
155 pending.push(rust_raknet::Bytes::from(payload(id, message + 20, size)));
156 if LOADED {
157 stamps[message % 16] = Instant::now();
158 }
159 sent += 1;
160 }
161 connection
162 .send_bytes_batch(&pending, Reliability::ReliableOrdered)
163 .await?;
164 while received < messages {
165 connection.recv_bytes_batch(&mut incoming, 16).await?;
166 for actual in &incoming {
167 expected[9..17].copy_from_slice(&((received + 20) as u64).to_le_bytes());
168 if actual.as_ref() != expected {
169 return Err::<_, BenchError>("echo payload or order mismatch".into());
170 }
171 if LOADED {
172 rtts.push(stamps[received % 16].elapsed().as_nanos());
173 }
174 received += 1;
175 }
176 pending.clear();
177 for _ in 0..incoming.len().min(messages - sent) {
178 pending.push(rust_raknet::Bytes::from(payload(id, sent + 20, size)));
179 if LOADED {
180 stamps[sent % 16] = Instant::now();
181 }
182 sent += 1;
183 }
184 if !pending.is_empty() {
185 connection
186 .send_bytes_batch(&pending, Reliability::ReliableOrdered)
187 .await?;
188 }
189 }
190 } else {
191 let mut sent = 0;
192 while sent < messages.min(16) {
193 outgoing[9..17].copy_from_slice(&((sent + 20) as u64).to_le_bytes());
194 if LOADED {
195 stamps[sent % 16] = Instant::now();
196 }
197 socket.send(&outgoing).await?;
198 sent += 1;
199 }
200 for received in 0..messages {
201 expected[9..17].copy_from_slice(&((received + 20) as u64).to_le_bytes());
202 socket.recv(size, &mut actual).await?;
203 if actual != expected {
204 return Err::<_, BenchError>("echo payload or order mismatch".into());
205 }
206 if LOADED {
207 rtts.push(stamps[received % 16].elapsed().as_nanos());
208 }
209 if sent < messages {
210 outgoing[9..17].copy_from_slice(&((sent + 20) as u64).to_le_bytes());
211 if LOADED {
212 stamps[sent % 16] = Instant::now();
213 }
214 socket.send(&outgoing).await?;
215 sent += 1;
216 }
217 }
218 }
219 // Keep every connection open until all peers finish the measured burst.
220 Ok::<_, BenchError>((socket, rtts))
221 });
222 }
223 barrier.wait().await;
224 let started = Instant::now();
225 start_gate.wait().await;
226 let mut retained = Vec::with_capacity(count);
227 let mut rtts = Vec::with_capacity(count * if LOADED { messages } else { 20 });
228 while let Some(result) = exchanges.join_next().await {
229 let (socket, values) = result??;
230 retained.push(socket);
231 rtts.extend(values);
232 }
233 let elapsed = started.elapsed().as_secs_f64();
234 println!("RTT samples: {}", rtts.len());
235 rtts.sort_unstable();
236 println!(
237 "Connections: {count}\nMessages per connection: {messages}\nPayload size: {size} bytes\nSetup: {setup_seconds:.6} s\nElapsed: {elapsed:.6} s"
238 );
239 println!(
240 "Echo payload throughput (per direction): {:.2} MiB/s",
241 count as f64 * messages as f64 * size as f64 / 1048576.0 / elapsed
242 );
243 println!(
244 "RTT p50: {:.1} us\nRTT p95: {:.1} us\nRTT p99: {:.1} us",
245 percentile(&rtts, 50),
246 percentile(&rtts, 95),
247 percentile(&rtts, 99)
248 );
249 println!(
250 "RTT measurement: {}",
251 if LOADED {
252 "per-message throughout measured burst"
253 } else {
254 "sequential warmup before burst"
255 }
256 );
257 println!("Verified ordered echoes: {}", count * (messages + 20));
258 drop(retained);
259 Ok(())
260}Sourcepub fn peer_addr(&self) -> Result<SocketAddr>
pub fn peer_addr(&self) -> Result<SocketAddr>
Sourcepub fn local_addr(&self) -> Result<SocketAddr>
pub fn local_addr(&self) -> Result<SocketAddr>
Sourcepub fn raknet_version(&self) -> Result<u8>
pub fn raknet_version(&self) -> Result<u8>
Return the RakNet protocol version used by this connection.