WebSocket Client And Server
Use this when the job is not "serve HTTP" but "upgrade and speak frames."
icey's WebSocket support lives in the HTTP module for a reason. The handshake is HTTP. After that, the connection is upgraded and the frame adapter takes over. That is the whole model.
The Shape
Client side:
createConnectionT(ws:// or wss://)
-> start()
-> HTTP handshake
-> Connect fires when the WebSocket handshake is complete
-> send/receive framed payloadServer side:
HTTP request with Upgrade: websocket
-> replaceAdapter(ws::ConnectionAdapter)
-> send 101 Switching Protocols
-> connection enters Upgraded mode
-> frame I/O from there onIf you need the underlying connection rules, read HTTP Lifecycle. This page is about the usable WebSocket path.
Client
The current sample does exactly this:
auto conn = http::createConnectionT<http::ClientConnection>(
http::URL("ws://echo.websocket.events"));
conn->Connect += [&]() {
conn->send("Hello!", 6, http::ws::Text);
};
conn->Payload += [](const MutableBuffer& buf) {
std::string data(bufferCast<const char*>(buf), buf.size());
std::cout << "Received: " << data << '\n';
};
conn->Close += [](http::Connection&) {
uv_stop(uv::defaultLoop());
};
conn->start();Two rules matter here:
start()starts the handshakeConnectfires after the WebSocket handshake succeeds, not after bare TCP connect
That second rule is important. It means application code does not race the handshake.
Frame Types
Outgoing frame type is controlled by the flags argument to send():
conn->send(text.data(), text.size(), http::ws::Text);
conn->send(binary.data(), binary.size(), http::ws::Binary);You are sending payload. The adapter handles framing.
Server Upgrade
On the server side, upgrade is explicit:
srv.Connection += [](http::ServerConnection::Ptr conn) {
if (conn->request().get("Upgrade") == "websocket") {
conn->replaceAdapter(
std::make_unique<http::ws::ConnectionAdapter>(
conn.get(), http::ws::ServerSide));
return;
}
conn->response().setStatus(http::StatusCode::OK);
conn->sendHeader();
conn->close();
};After that point:
- the connection stays upgraded until close
- HTTP keep-alive rules stop applying
- outgoing
send()goes through the WebSocket adapter - incoming
Payloadis application payload, not raw frame bytes
That last point is one of the main benefits of the adapter layer.
Fragmentation And Partial Frames
The application does not have to reassemble WebSocket fragmentation by hand.
icey's framer:
- buffers partial frames split across TCP reads
- reassembles fragmented messages
- enforces the RFC 6455 control-frame rules
- applies masking rules automatically based on client or server mode
Payload receives complete application messages, not raw frame fragments.
That is how it should be. Fragmentation is transport detail, not application protocol.
Ping, Pong, And Close
Ping and pong are handled inside the adapter.
- incoming
Pinggets aPong - incoming
Pongis consumed internally - close frames drive the close handshake
If you want to close explicitly, call shutdown() on the adapter:
auto* adapter = static_cast<http::ws::ConnectionAdapter*>(conn->adapter());
adapter->shutdown(
static_cast<uint16_t>(http::ws::CloseStatusCode::NormalClose),
"goodbye");That is different from just tearing down the underlying TCP socket. It gives the peer a proper WebSocket close frame first.
Client vs Server Responsibilities
icey handles the RFC rules that should not be application boilerplate:
- client payload masking
- server-side unmasked frame enforcement
- RSV and opcode validation
- control-frame length and FIN rules
- fragmentation reassembly
Application code still owns:
- what messages mean
- whether payload is text or binary
- when to close
- how to react to errors or disconnects
Debugging Order
If a WebSocket path is not working, debug it in this order:
- plain HTTP reachability
- handshake success
- upgrade on the server
- framed send path
- application payload handling
Do not start by debugging your JSON message layer if the upgrade never completed.
Good Next Stops
- HTTP guide for the full HTTP and WebSocket surface
- HTTP Lifecycle for upgrade and connection-state detail
- HTTP Server for the plain request/response path around it
wsclientfor the runnable client sample
