Chapter 7: WebSocket
This chapter covers WebSocket handshake validation, callback types, text/binary frames, heartbeat, and close behavior.
1. Lifecycle callbacks
| Stage | API | Result |
|---|---|---|
| Before handshake | setJudgeFunction | bool; false rejects the connection. |
| After successful handshake | setStartFunction | bool; suitable for a welcome frame. |
| Ordinary message | setGlobalSolveFunction | bool; false signals failure and close. |
| Keyed multi-stage message | setGetKeyFunction + setFunction | int with 1/0/-1/-2 flow semantics. |
2. Complete echo demo
#include <sttnet.h>
#include <iostream>
#include <string_view>
int main()
{
using namespace stt::network;
using namespace stt::data;
using stt::system::ServerSetting;
if(!ServerSetting::blockTerminationSignals())
{
std::cerr << "failed to block termination signals\n";
return 1;
}
WebSocketServer server;
// Check the HTTP upgrade request before accepting the WebSocket handshake.
// This demo accepts only /echo and an optional query string.
server.setJudgeFunction(
[](WebSocketFDInformation &connection) {
const bool correctPath =
connection.locPara == "/echo" ||
connection.locPara.rfind("/echo?", 0) == 0;
// A real service may also inspect connection.header here, for
// example with HttpStringUtil::get_value_header().
return correctPath;
});
// The global callback receives messages that do not use a custom key route.
// It returns bool: false tells STTNet that message handling failed.
server.setGlobalSolveFunction(
[](WebSocketServerFDHandler &client,
WebSocketFDInformation &message) {
// RFC 6455 opcode 1 is text and opcode 2 is binary.
const std::string frameType =
message.message_type == 2 ? "0010" : "0001";
// Echo the payload using the same text/binary frame type.
return client.sendMessage(message.message, frameType);
});
// Close idle connections and require a heartbeat response within 30 seconds.
server.setTimeOutTime(20); // Idle timeout in minutes.
server.setHBTimeOutTime(30); // Heartbeat response timeout in seconds.
if(!server.startListen(5050))
{
std::cerr << "failed to listen on port 5050\n";
return 2;
}
std::cout << "WebSocket echo listening on ws://127.0.0.1:5050/echo\n";
ServerSetting::waitForTerminationSignal();
return server.close() ? 0 : 3;
}3. Validate handshake headers
server.setJudgeFunction([](WebSocketFDInformation &info) {
std::string_view token;
stt::data::HttpStringUtil::get_value_header(
std::string_view(info.header), token, "X-Demo-Token");
return info.locPara == "/echo" && token == "sttnet";
});4. Frame types
- Opcode 1 represents text and uses send type
"0001". - Opcode 2 represents binary data and uses send type
"0010". - Ping/Pong is protocol-level liveness, not a complete application presence model.
- Protocol-level close uses a WebSocket close frame such as
closeFD(fd, 1000, "bye").
5. Test
./build/examples/sttnet_websocket_echo
websocat ws://127.0.0.1:5050/echo