Expand description
Tokio-native typed TCP/UDP pipeline framework inspired by Netty.
rs-netty keeps the familiar channel, pipeline, and handler shape while
using Rust’s type system to validate pipeline order and message transitions
at compile time.
§Quick start
use rs_netty::{codec::LineCodec, handler, pipeline, Result, TcpServer};
#[tokio::main]
async fn main() -> Result<()> {
TcpServer::bind("127.0.0.1:9000")
.pipeline(|| {
pipeline()
.codec(LineCodec::new())
.handler(Echo)
})
.run()
.await
}
struct Echo;
#[handler(Echo)]
async fn echo(msg: String) -> Result<String> {
Ok(msg)
}§Pipeline shape
TCP pipelines are built with pipeline() and UDP pipelines are built with
datagram_pipeline(). The builder only exposes methods that are valid in
the current state, so invalid orderings such as adding a handler before a
codec fail to compile.
A TCP pipeline has this shape:
codec -> inbound* -> business* -> handler -> outbound*A UDP pipeline has the same typed stage model, but processes whole datagrams rather than a byte stream.
§Write and flush semantics
Writes issued through Context are staged in the current handler’s
outbox and then encoded into the connection write buffer. flush and
write_and_flush request a local socket flush immediately; dropping their
returned handles is fire-and-forget, while awaiting them waits until the
local socket write completes. DatagramContext keeps the same manual
flush model for datagram sockets.
Writes issued through Channel, TcpClientHandle, DatagramChannel,
or UdpClientHandle are sent through the connection/socket command queue
and follow the same manual flush semantics. The queue is bounded by the
configured outbound queue size.
§Handler ergonomics
Simple handlers can use the handler attribute macro:
struct Echo;
#[handler(Echo)]
async fn echo(msg: String) -> Result<String> {
Ok(msg)
}A handler function that returns Result<Out> automatically writes and
flushes Out back through the pipeline. A function that returns Result<()>
consumes the inbound message without automatically writing; in that case use
#[handler(TypeName, write = WriteType)] so the macro can set
Handler::Write.
Write a manual Handler or DatagramHandler implementation when the
logic needs direct access to Context or DatagramContext, such as
explicit flush timing or multiple writes for one inbound message.
§Client pipeline choices
TcpClient::pipeline accepts a reusable factory closure, matching the
server API and working well for stateless or cloneable client handlers.
TcpClient::pipeline_instance accepts one already-built pipeline and
consumes it when the client connects. Prefer pipeline_instance when a
client handler owns one-shot state, such as tokio::sync::oneshot::Sender.
Re-exports§
pub use channel::Channel;pub use channel::DatagramChannel;pub use context::BusinessContext;pub use context::ConnInfo;pub use context::ConnectionStats;pub use context::Context;pub use context::DatagramContext;pub use context::DatagramInfo;pub use context::InboundContext;pub use context::OutboundContext;pub use error::Error;pub use error::Result;pub use life::CloseReason;pub use life::Life;pub use life::NoLife;pub use pipeline::builder::pipeline;pub use pipeline::datagram::builder::datagram_pipeline;pub use traits::Business;pub use traits::DatagramHandler;pub use traits::Flow;pub use traits::Handler;pub use traits::Inbound;pub use traits::Outbound;pub use transport::tcp::client::TcpClient;pub use transport::tcp::client::TcpClientHandle;pub use transport::tcp::server::TcpServer;pub use transport::udp::client::UdpClient;pub use transport::udp::client::UdpClientHandle;pub use transport::udp::server::UdpServer;
Modules§
Attribute Macros§
- handler
- Adapts an async function into an
rs_netty::Handlerimplementation.