std.ws

WebSocket client.

import std.ws

conn = ws.connect("wss://example.com/socket")
ws.send(conn, "hello")
msg = ws.recv(conn)          # blocks
ws.close(conn)

Needs net.

Receiving

recv blocks until a message arrives, and returns null when the connection closes. So the idiomatic loop ends on close:

loop {
    msg = ws.recv(conn)
    if msg == null { break }
    handle(msg)
}

Server side

The upgrade lives in std.http, which can turn a request into a WebSocket connection. ECKO_MAX_WS_CONNS (default 1024) bounds concurrent connections - a bound that matters, since each one holds resources for as long as the client keeps it open.

Concurrency

A connection is not a value you copy - do not use one from several tasks at once. The usual arrangement is one task reading and a channel carrying messages to whatever processes them, which also gives you backpressure.

Errors

Failures raise { kind: "net" }. Network connections drop, so a long-lived client needs reconnection logic - ws.recv returning null is where you notice.

When SSE is the better choice

For one-directional streaming from server to client, server-sent events over plain HTTP are simpler: no upgrade, no framing, no separate protocol for proxies to handle, and browsers reconnect automatically. See Streaming responses & SSE.

Use WebSockets when the client genuinely needs to send messages mid-stream - a chat, a collaborative editor, a game.

Higher level

For a Redis-style protocol client written over raw sockets, see std.net and the client packages built on it.