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 |
#626 in Network programming
125 downloads per month
260KB
6.5K
SLoC
Yet another project rewritten in Rust.
Features
Stream
/Sink
/Future
based async API.- Low level API but easy to use.
- RakNet features:
- Support
Unreliable
,Reliable
andReliableOrdered
packets. - Support multiple order channels.
- Support
ACK
/NACK
mechanism.
- 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
~3–12MB
~135K SLoC