Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transport Protocols

Transport protocols form the foundation of communication in networked applications. In Rama, they’re not just a substrate—they’re fully integrated, layered services, treated with the same flexibility and modularity as higher-level components. This chapter explores how Rama supports and enhances TCP, UDP, QUIC, and Unix sockets, emwpoering you to build robust and performant network applications.

Rama’s layered architecture starts at the transport layer and goes all the way up. This is a distinguishing trait: in most frameworks, transport is considered a low-level concern that you configure once and forget. But in Rama, transport protocols are first-class citizens. They participate in the same service stack as application protocols, middleware, observability tools, and business logic.

Streams and Datagrams

Before diving into specific protocols, it’s important to understand the two primary transport abstractions: streams and datagrams.

  • Streams (like those provided by TCP and Unix stream sockets) represent ordered, reliable, connection-oriented communication. They guarantee delivery and preserve the order of bytes.
  • Datagrams (like those used in UDP and Unix datagram sockets) represent unordered, unreliable, connectionless communication. Each message stands alone.

Each abstraction has different strengths and trade-offs. Streams are great for general-purpose applications like HTTP, SSH, and database access. Datagrams are perfect for high-performance, latency-sensitive applications like DNS, real-time telemetry, or custom RPC protocols.

Note that H3 is built upon UDP by layering QUIC in between for the same ordered and reliable connection-oriented communication traditionally offered by TCP.

QUIC sits between the two. It runs over UDP and carries many independent streams on one connection, each of them ordered and reliable on its own. Ordering is per-stream, not connection-wide: a stream that loses a packet does not hold up the others, which is what distinguishes it from carrying several exchanges over one TCP connection. It also carries unreliable DATAGRAM frames, which are neither ordered nor retransmitted and are bounded by what one packet can hold.

Rama’s QUIC is the transport itself. HTTP/3 is not part of it.

It speaks QUIC v1 (RFC 9000) and v2 (RFC 9369) and negotiates between them per RFC 9368, with downgrade protection. A connection starts in v1 and accepts both by default; rama::quic::version::ClientVersionPolicy and ServerVersionPolicy change what is offered and accepted. A BoringSSL client can switch version mid-handshake, a Rustls one cannot. Address tokens and TLS tickets are scoped to the version that issued them.

Remote vs Local

Another dimension in transport protocol design is remote vs local communication:

  • Remote transports like TCP, UDP and QUIC operate over the network stack and are ideal for client-server or peer-to-peer communication across machines.
  • Local transports like Unix domain sockets (UDS) operate within a single host, using the filesystem as an addressing mechanism.

Unix sockets are especially useful for high-performance, secure inter-process communication (IPC). They avoid the overhead of TCP while retaining the benefits of stream or datagram semantics. In Rama, using Unix (Domain) Sockets (UDS) is as simple as switching out the transport service—your layers, middleware, and application logic don’t need to change.

Use Cases and Trade-offs

ProtocolAbstractionCommunicationReliableOrderedTypical Uses
TCPStreamRemote✅✅HTTP, SSH, DBs
UDPDatagramRemote❌❌DNS, VoIP, custom RPC
QUICStream/DatagramRemote✅/❌per stream/❌Multiplexed RPC, tunneling, real-time media
UnixStream/DatagramLocal✅/❌✅/❌IPC, reverse proxies, system daemons

Each protocol has its place in the network programming toolbox. In Rama, your choice of protocol doesn’t lock you into a specific architecture. Because the transport is just another service, you can build once and deploy across protocols with minimal changes.

Note that typical uses do not mean that these are the only uses or that a use mentioned for 1 protocol cannot be served by another one. As usually it’s a set of trade offs.

This transport-first model is also part of why Rama’s gRPC support fits naturally in the framework: gRPC often runs over HTTP/2, but the transport and lower networking concerns remain fully programmable.

Integration in Rama

QUIC needs the quic feature and a TLS provider. Built-in providers use either boring, or rustls together with ring or aws-lc. Inject BoringTlsProvider or RustlsTlsProvider through the QUIC configuration factory; automatic selection prefers Rustls when both are available. Custom implementations use the same QuicClientConfigProvider and QuicServerConfigProvider interfaces, without enabling a built-in TLS provider. The lower-level TLS session interfaces remain available too. QUIC is built on rama-udp, so its socket options and packet features apply. Boring builds do not require Rustls, ring, or AWS-LC.

You can also bring your own TLS. The traits in rama::quic::tls::provider describe what QUIC needs from a TLS 1.3 implementation and its packet protection; implement them for the library of your choice and pass the result to ClientConfig::new and ServerConfig::new, with only the quic feature enabled. The GnuTLS interop project is a complete example: it drives QUIC with GnuTLS, in both roles, against aioquic.

For the connection-oriented streams there are also connectors to make it easy to establish connections in bigger stacks (e.g. http within tls on top of tcp):

Rama can also enumerate the host’s own network interfaces and the addresses assigned to them, e.g. to discover which devices exist prior to binding, or for diagnostics (rama probe iface):

Examples

These examples show how easy it is to set up and extend Rama’s transport services, and how they integrate seamlessly with the rest of the stack.

Rama doesn’t just support networking—it is networking, from transport to application.