-
Notifications
You must be signed in to change notification settings - Fork 0
WebSocket SSE
github-actions[bot] edited this page Jan 28, 2026
·
18 revisions
Elio provides full support for WebSocket (RFC 6455) and Server-Sent Events (SSE) for real-time bidirectional and unidirectional communication.
WebSocket provides full-duplex communication channels over a single TCP connection.
#include <elio/elio.hpp>
#include <elio/http/websocket.hpp>
using namespace elio;
using namespace elio::http::websocket;
// WebSocket message handler
coro::task<void> echo_handler(ws_connection& conn) {
while (conn.is_open()) {
auto msg = co_await conn.receive();
if (!msg) break;
// Echo back the message
if (msg->type == opcode::text) {
co_await conn.send_text(msg->data);
} else if (msg->type == opcode::binary) {
co_await conn.send_binary(msg->data);
}
}
}
int main() {
// Create WebSocket-enabled router
ws_router router;
// Regular HTTP routes
router.get("/", [](context& ctx) -> coro::task<response> {
co_return response::ok("Hello!");
});
// WebSocket routes
server_config ws_config;
ws_config.max_message_size = 1024 * 1024; // 1MB
router.websocket("/ws", echo_handler, ws_config);
// Create and start server
ws_server srv(std::move(router));
runtime::scheduler sched(4);
sched.start();
auto task = srv.listen(net::ipv4_address(8080));
sched.spawn(task.release());
// Run until stopped...
sched.shutdown();
return 0;
}#include <elio/elio.hpp>
#include <elio/http/websocket.hpp>
using namespace elio;
using namespace elio::http::websocket;
coro::task<void> connect_example() {
// Create client
client_config config;
config.subprotocols = {"chat", "json"}; // Optional subprotocols
ws_client client(config);
// Connect to server
if (!co_await client.connect("ws://localhost:8080/ws")) {
ELIO_LOG_ERROR("Failed to connect");
co_return;
}
ELIO_LOG_INFO("Connected! Subprotocol: {}", client.subprotocol());
// Send messages
co_await client.send_text("Hello, server!");
co_await client.send_binary("\x01\x02\x03");
// Receive messages
while (client.is_open()) {
auto msg = co_await client.receive();
if (!msg) break;
if (msg->type == opcode::text) {
ELIO_LOG_INFO("Received: {}", msg->data);
}
}
// Close connection
co_await client.close(close_code::normal, "Done");
}| Opcode | Name | Description |
|---|---|---|
| 0x0 | continuation | Continuation of fragmented message |
| 0x1 | text | UTF-8 text data |
| 0x2 | binary | Binary data |
| 0x8 | close | Connection close |
| 0x9 | ping | Ping (keep-alive) |
| 0xA | pong | Pong (response to ping) |
| Code | Name | Description |
|---|---|---|
| 1000 | normal | Normal closure |
| 1001 | going_away | Endpoint going away |
| 1002 | protocol_error | Protocol error |
| 1003 | unsupported | Unsupported data type |
| 1008 | policy_violation | Policy violation |
| 1009 | too_large | Message too big |
| 1011 | unexpected | Unexpected condition |
For secure connections, use wss:// URLs and configure TLS:
// Server with TLS
auto tls_ctx = tls::tls_context::make_server("cert.pem", "key.pem");
auto task = srv.listen_tls(net::ipv4_address(8443),
io::default_io_context(), sched, tls_ctx);
// Client with TLS
ws_client client(ctx);
client.tls_context().use_default_verify_paths();
co_await client.connect("wss://example.com/ws");SSE provides server-to-client event streaming over HTTP.
#include <elio/elio.hpp>
#include <elio/http/sse.hpp>
using namespace elio;
using namespace elio::http::sse;
// Event stream handler
coro::task<void> event_stream(sse_connection& conn) {
int counter = 0;
// Send retry interval
co_await conn.send_retry(3000); // 3 seconds
while (conn.is_active()) {
++counter;
// Send a simple event
co_await conn.send_data("Counter: " + std::to_string(counter));
// Send a typed event
event evt = event::full(
std::to_string(counter), // id
"update", // type
R"({"count":)" + std::to_string(counter) + "}"
);
co_await conn.send(evt);
// Wait before next event
co_await time::sleep_for(std::chrono::seconds(1));
}
}#include <elio/elio.hpp>
#include <elio/http/sse.hpp>
using namespace elio;
using namespace elio::http::sse;
coro::task<void> listen_events() {
auto& ctx = io::default_io_context();
// Configure client
client_config config;
config.auto_reconnect = true;
config.default_retry_ms = 3000;
sse_client client(ctx, config);
// Connect
if (!co_await client.connect("http://localhost:8080/events")) {
ELIO_LOG_ERROR("Failed to connect");
co_return;
}
// Receive events
while (client.is_connected()) {
auto evt = co_await client.receive();
if (!evt) break;
ELIO_LOG_INFO("Event: type={} id={} data={}",
evt->type.empty() ? "message" : evt->type,
evt->id,
evt->data);
}
}SSE events are formatted as text with specific fields:
id: event-123
event: notification
retry: 3000
data: Hello, World!
data: This is line 2
-
id:- Event ID for reconnection tracking -
event:- Event type (default: "message") -
retry:- Reconnection interval in milliseconds -
data:- Event data (can span multiple lines) - Empty line marks end of event
| Feature | SSE | WebSocket |
|---|---|---|
| Direction | Server → Client only | Bidirectional |
| Protocol | HTTP | Custom over TCP |
| Reconnection | Automatic | Manual |
| Browser support | EventSource API | WebSocket API |
| Complexity | Simple | More complex |
| Best for | Notifications, feeds | Chat, games, real-time |
- Real-time notifications
- Live feeds (news, stocks)
- Progress updates
- Log streaming
- Any server-push scenario without client messages
- Chat applications
- Real-time games
- Collaborative editing
- Any scenario requiring bidirectional communication
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onopen = () => {
console.log('Connected');
ws.send('Hello, server!');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
ws.onclose = (event) => {
console.log('Disconnected:', event.code);
};
// Send messages
ws.send('Hello');
ws.send(new Blob([1, 2, 3]));
// Close
ws.close(1000, 'Done');const es = new EventSource('/events');
es.onmessage = (event) => {
console.log('Message:', event.data);
};
es.addEventListener('notification', (event) => {
console.log('Notification:', event.data);
console.log('ID:', event.lastEventId);
});
es.onerror = (error) => {
console.error('Error:', error);
// EventSource will auto-reconnect
};
// Close
es.close();Complete examples are available:
-
examples/websocket_server.cpp- WebSocket server with echo and chat -
examples/websocket_client.cpp- WebSocket client demo -
examples/sse_server.cpp- SSE event streaming server -
examples/sse_client.cpp- SSE event receiver
- See API Reference for detailed API documentation
- See Networking for TCP and HTTP documentation
- See Examples for more code examples