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.
API Quick Tour
This is a quick tour of the WebSockets server API.
When a WebSockets connection request is received by the Ioto web server, the HTTP upgrade
header will instruct Ioto to upgrade the connection to use WebSockets.
To respond to the connection, you should define an action
routine to be invoked when the connection is established. 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 WebSockets request is received, your myAction
function will be invoked:
static void myAction(Web *web)
{
webAsync(web, onRead, web);
// Run web sockets until closed and invoke onEvent for each incoming message and event
if (webWait(web, onEvent) < 0) {
// Error
}
// Closed
}
The webAsync
routine defines a callback routine to invoke for incoming WebSocket messages, errors and connection events. The webWait
routine blocks until the WebSocket connection is closed.
If the connection is closed, webWait
will return a value <= 0. If less than zero, the socket was closed due to an error. If the API returns zero, the connection has been orderly closed.
void onEvent(WebSocket *ws, int event, char *buf, ssize len, void *arg)
{
switch (event) {
case WS_EVENT_OPEN:
case WS_EVENT_CLOSE:
case WS_EVENT_ERROR:
break;
case WS_EVENT_MESSAGE:
case WS_EVENT_PARTIAL_MESSAGE:
printf("Received %s\n", buf);
webSocketSend(ws, "%s", "Response message");
break;
}
}
To send a message to the peer, use webSocketSend
:
// Send a message to the client
webSocketSend(web->webSocket, "WebSocket connected");
To close the connection, you can call webSocketSendBlock
with a close message type.
webSocketSendClose(web->webSocket, status, reason);
or alternatively, call webFinalize
which will close the HTTP connection and the WebSocket connection.
webFinalize(web);
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