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.
Path | Default | Description |
---|---|---|
limits.maxMessage | MAXINT | Define the maximum message size. |
limits.maxFrame | 131072 | Define the maximum frame size. |
webSockets.ping | none | Define the ping keep-alive message frequency. |
webSockets.protocol | chat | Define the application-level sub-protocol. |
webSockets.validateUTF | true | Enable 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.
webAddAction(host, "/test/websockets", myAction, NULL);
When a request is received, your myAction
function will be invoked:
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.
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:
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
- RFC 6455 - The WebSockets Protocol
- WebSocket API - The Javascript WebSockets API
- WebSockets Wikipedia - WebSockets Wikipedia