Skip to content

Server WebSockets

The Ioto web server supports WebSockets for bidirectional, full-duplex communications over persistent TCP/IP connections. A WebSocket connection is established over a standard HTTP connection using a GET request and is then upgraded without impacting the original connection.

Read the WebSockets Library for background first.

Configuration

To configure WebSockets in the web server, define a request route for web sockets requests. This route ill use a unique URI prefix for WebSocket communications and configure the action handler to be invoked upon receipt of a connection requeset.

routes: [
    { match: '/upload/', methods: ['DELETE', 'GET', 'PUT'] },
    { match: '/ws/', methods: ['GET'], handler: 'action' },
    { /* Catch all */ },
],

WebSockets is configured via several web.json5 configuration directives.

PathDefaultDescription
limits.maxMessageMAXINTDefine the maximum message size.
limits.maxFrame131072Define the maximum frame size.
webSockets.pingnoneDefine the ping keep-alive message frequency.
webSockets.protocolchatDefine the application-level sub-protocol.
webSockets.validateUTFtrueEnable validation of UTF8 message.

When WebSockets messages are sent, they may be divided into frames. On receipt, the client will aggregate into a unified message.

Actions

To receive and send messages, you typically define an Action handler function that is invoked when a request is received on the define route.

To define the action function, specify the request URL and provide the function to invoke. This definition should be placed in your Ioto ioStart routine.

c
webAddAction(host, "/test/websockets", myAction, NULL);

When a request is received, your myAction function will be invoked:

c
static void myAction(Web *web)
{
    ssize rc;

    //  Send a message to the client
    webSocketSend(web->webSocket, "WebSocket connected");

    //  Run web sockets until closed and invoke onRead for each incoming message.
    if ((rc = webSocketRun(web, onRead)) <= 0) {
        if (rc < 0) {
            //  Error
        }
        // Closed
    }
}

When a WebSockets message is received, your onRead callback will be invoked.

c
static void onRead(WebSocket *ws, cchar *buf, ssize len)
{
    printf("Received message %s\n", buf);
    //  Send a message. Here just echo the message
    webSocketSend(ws, "%s", buf);
}

Keep Alive

To keep a communications channel alive, it is sometimes necessary to send regular messages to indicate the channel is still being used. Some servers, browsers, or proxies may close an idle connection. The Ping/Pong WebSockets messages are designed to send non-application-level traffic that will prevent the channel from being prematurely closed.

Automatic ping message can be sent from the web server by setting the webSockets.ping directive to the desired frequency. For example:

json5
webSockets {
    ping: '1min'
}

Timeouts

The standard Ioto request and inactivity timeouts can be used for WebSocket communications by defining the timeouts.request and timeouts.inactivity web.json5 directives. These are the same request and inactivity timeouts used for ordinary requests.

You can extend the timeouts by calling webUpdateDeadline in your onRead callback whenever a message is received or sent.

timeouts: {
    inactivity: '5 mins',
    request: '1 hour',
},

API

References