5 releases
| 0.1.4 | Oct 15, 2024 |
|---|---|
| 0.1.3 | Jul 20, 2024 |
| 0.1.2 | Jul 17, 2024 |
| 0.1.1 | Feb 10, 2024 |
| 0.1.0 | Feb 9, 2024 |
#3 in #raknet
373 downloads per month
260KB
6.5K
SLoC
Yet another project rewritten in Rust.
Features
Stream/Sink/Futurebased async API.- Low level API but easy to use.
- RakNet features:
- Support
Unreliable,ReliableandReliableOrderedpackets. - Support multiple order channels.
- Support
ACK/NACKmechanism.
- Support
- Full tracing:
- You can track a packet's span during deduplication, fragmentation, ...
Roadmap
Ordered by priority
- Documentation
- Simulation testing
- Bulk benchmark
- AF_XDP socket & XDP redirect from UDP
- Optimize performance for single thread runtime (IO without Send)
- Robust client implementation
- Use stable rust toolchain (
I like nightly)
Getting Started
See examples or integration testing for basic usage.
Server
Most operations are performed on Stream and Sink. There will be some options in opts.
The implementation details are obscured, and you can only see a very high level of abstraction, including the Error type, which is just std::io::Error.
Keep polling incoming because it also serves as the router to every connections.
Apply Sink::poll_flush to IO will trigger to flush all pending packets, ACK/NACK, and stale packets. So you have to call poll_flush periodically. You can configure the flush strategy you want.
Apply Sink::poll_close to IO will ensure that all data is received by the peer before returning. It may keep resending infinitely unless you cancel the task. So you'd better set a timeout for each poll_close.
[!NOTE] All calculations are lazy. The state will not update if you do not poll it.
use bytes::Bytes;
use futures::{SinkExt, StreamExt};
use raknet_rs::server::{self, MakeIncoming};
let socket = tokio::net::UdpSocket::bind("127.0.0.1:0").await?;
let config = server::Config::new()
.send_buf_cap(1024)
.sever_guid(114514)
.advertisement(&b"Hello, I am server"[..])
...
let mut incoming = socket.make_incoming(config);
let (reader, _) = incoming.next().await.unwrap();
tokio::pin!(reader);
let data: Bytes = reader.next().await.unwrap();
Client
[!WARNING] The current version of the client only has the most basic handshake implementation, and it is not recommended to use it directly.
use bytes::Bytes;
use futures::{SinkExt, StreamExt};
use raknet_rs::client::{self, ConnectTo};
use raknet_rs::Reliability;
let socket = tokio::net::UdpSocket::bind("0.0.0.0:0").await?;
let config = client::Config::new()
.send_buf_cap(1024)
.client_guid(1919810)
...
let (_, writer) = socket.connect_to(<addr>, config).await?;
tokio::pin!(writer);
writer.send(Message::new(Reliability::Reliable, 0, Bytes::from_static(b"Hello, Anyone there?")))
.await?;
Dependencies
~4–16MB
~148K SLoC