Skip to content

WebSocket Transport

WebSocket transports keep a single TCP connection open while multiplexing many RPC calls. They are ideal for real-time dashboards, collaborative apps, and scenarios where the client needs to push updates back to the server without re-establishing a connection for every request.

  • Bidirectional updates – UI clients can send commands while receiving streaming responses in the same session.
  • Low-latency push – avoid the overhead of repeatedly negotiating HTTP connections when servers need to push data immediately.
  • Firewall friendly – works when only a single outbound port (such as 443) is allowed.

Create a caller-side transport with RpcWebSocketCallerTransport.connect and pass it to a RpcCallerEndpoint:

import 'package:rpc_dart_transports/rpc_dart_transports.dart';
Future<void> main() async {
final transport = RpcWebSocketCallerTransport.connect(
Uri.parse('wss://api.example.com/rpc'),
protocols: const ['rpc-dart'],
logger: RpcLogger('WebSocketClient'),
);
final caller = RpcCallerEndpoint(transport: transport);
final chat = ChatCaller(caller);
final stream = chat.joinRoom('general', 'u-42');
stream.listen((message) => print('[$message]'));
}

RpcWebSocketCallerTransport.connect automatically configures a reconnection factory so you can call transport.reconnect() if the socket is dropped.

Use RpcWebSocketServer when you already have a source of upgraded WebSocketChannels (for example via shelf_web_socket or a custom HttpServer):

final connections = controller.stream; // Stream<WebSocketChannel>
final server = RpcWebSocketServer.createWithContracts(
connections: connections,
port: 8080,
contracts: [ChatResponder()],
logger: RpcLogger('WebSocketServer'),
);
await server.start();

For lower-level control you can create RpcWebSocketResponderTransport directly from a WebSocketChannel and pass it to RpcResponderEndpoint.

RpcWebSocketTransportBase exposes the same hooks as other transports in the toolkit. You can combine mixins to add buffering or automatic reconnection:

class ResilientWebSocketTransport extends RpcWebSocketTransportBase
with RpcAutoReconnect, RpcMessageBuffering {
ResilientWebSocketTransport(WebSocketChannel channel)
: super(channel, logger: RpcLogger('ResilientWs'));
@override
RpcStreamIdManager get idManager => RpcStreamIdManager(isClient: true);
@override
bool get isClient => true;
}

Use RpcZeroCopySupport only for transports that remain inside a single process; WebSocket transports normally serialise payloads for the wire.

All WebSocket transports implement IRpcTransport, so you can:

  • Call transport.health() to obtain RpcHealthStatus snapshots.
  • Trigger a reconnection with transport.reconnect() (client side).
  • Close the socket via transport.close() when the endpoint shuts down.

Pair these diagnostics with RpcEndpoint.health() and RpcEndpointPingProtocol from the core library to build dashboards and alerting around connection health.