Skip to content

WebSocket Skill

Real-time bidirectional WebSocket communication: server-side event handling, message sending, and configuration.

Invoke with: /websocket

Key APIs

c
/* Event loop */
int webSocketRun(WebSocket *ws, WebSocketProc callback, void *arg, RBuf *buf, Ticks timeout);

/* Sending */
ssize webSocketSend(WebSocket *ws, cchar *fmt, ...);
ssize webSocketSendString(WebSocket *ws, cchar *buf);
ssize webSocketSendJson(WebSocket *ws, Json *json, int nid, cchar *key);
ssize webSocketSendBlock(WebSocket *ws, int type, cchar *msg, size_t len);
ssize webSocketSendClose(WebSocket *ws, int status, cchar *reason);

Event Types

EventDescription
WS_EVENT_OPENConnection established
WS_EVENT_MESSAGEComplete message received
WS_EVENT_PARTIAL_MESSAGEFragment of a multi-frame message
WS_EVENT_ERRORProtocol error occurred
WS_EVENT_CLOSEConnection closed

Server-Side Handler

c
static void onWebSocket(WebSocket *ws, int event, cchar *buf, size_t len, void *arg)
{
    switch (event) {
    case WS_EVENT_OPEN:
        rInfo("ws", "Client connected");
        break;
    case WS_EVENT_MESSAGE:
        webSocketSend(ws, "echo: %s", buf);
        break;
    case WS_EVENT_CLOSE:
        rInfo("ws", "Client disconnected: %s", webSocketGetCloseReason(ws));
        break;
    case WS_EVENT_ERROR:
        rError("ws", "Error: %s", webSocketGetErrorMessage(ws));
        break;
    }
}

webSocketRun(ws, onWebSocket, NULL, NULL, 30000);

Sending JSON Data

c
Json *data = jsonAlloc();
jsonSetString(data, 0, "type", "telemetry");
jsonSetNum(data, 0, "temperature", 23);
jsonSetNum(data, 0, "humidity", 65);
webSocketSendJson(ws, data, 0, NULL);
jsonFree(data);

Per-Connection State

c
typedef struct {
    cchar *userId;
    int    sessionId;
} WsSession;

WsSession *session = rAllocType(WsSession);
session->userId = sclone("admin");
webSocketSetData(ws, session);

/* Retrieve in callback */
WsSession *s = webSocketGetData(ws);

Configuration

json5
{
    web: {
        webSockets: {
            protocol: 'chat',
            ping: 'never',
        },
        routes: [
            { match: '/ws/', handler: 'action' },
            { match: '/',    handler: 'file', documents: './site' },
        ],
    }
}

Important Notes

  • WebSocket events run in fibers — I/O calls yield cooperatively.
  • Automatic frame reassembly for fragmented messages.
  • Use webSocketSetLimits() to control max frame and message sizes.
  • Always handle WS_EVENT_CLOSE for cleanup.