Market Data Feed via WebSocket
Live demo — connecting to wss://ws.kraken.com/v2 and subscribing to real-time ticker data for BTC/USD, XRP/USD, ETH/USD, and DOGE/USD:
How It Works
TResolver DNS: ws.kraken.com → IP
│
TSocket.Connect(addr) TCP connection
│
TSslContext::Client()
TSslSocket.Connect(addr) TLS handshake (wss://)
│
TWebSocket.Connect(...) HTTP Upgrade to WebSocket
│
ws.SendText(subscribe) JSON subscription command
│
ws.ReceiveText() loop incoming ticker frames
Full source: wsclient.cpp
Complete Example
#include <coroio/all.hpp>
#include <coroio/ws/ws.hpp>
#include <coroio/dns/resolver.hpp>
using namespace NNet;
// Read loop runs concurrently with the send loop
template<typename TWebSocket>
TFuture<void> readLoop(TWebSocket& ws) {
while (true) {
auto msg = co_await ws.ReceiveText(); // string_view, valid until next call
std::cerr << msg << "\n";
}
co_return;
}
template<typename TPoller>
TFuture<void> marketData(TPoller& poller) {
// 1. Resolve hostname
TResolver resolver(poller);
TAddress addr = co_await THostPort("ws.kraken.com", 443).Resolve(resolver);
// 2. Open TCP connection
typename TPoller::TSocket tcp(poller, addr.Domain());
// 3. Wrap with TLS (wss://)
TSslContext ctx = TSslContext::Client();
TSslSocket ssl(std::move(tcp), ctx);
ssl.SslSetTlsExtHostName("ws.kraken.com"); // SNI — must be before Connect
co_await ssl.Connect(addr);
// 4. WebSocket handshake
TWebSocket ws(ssl);
co_await ws.Connect("ws.kraken.com", "/v2");
// 5. Subscribe
co_await ws.SendText(R"({
"method": "subscribe",
"params": {
"channel": "ticker",
"symbol": ["BTC/USD", "XRP/USD", "ETH/USD", "DOGE/USD"]
}
})");
// 6. Receive loop
co_await readLoop(ws);
co_return;
}
int main() {
TInitializer init;
TLoop<TDefaultPoller> loop;
auto h = marketData(loop.Poller());
loop.Loop();
}
Plain WebSocket (ws://)
For unencrypted connections, skip TLS and connect the raw socket directly:
typename TPoller::TSocket tcp(poller, addr.Domain());
co_await tcp.Connect(addr);
TWebSocket ws(tcp);
co_await ws.Connect("echo.websocket.org", "/");
Reading Lines from stdin and Sending
The full wsclient.cpp example also reads from stdin and sends each line as a text frame — useful for interactive WebSocket sessions:
TFileHandle stdin_fd{0, poller};
TLineReader lineReader(stdin_fd, 4096);
auto receiver = readLoop(ws); // runs concurrently
while (auto line = co_await lineReader.Read()) {
std::string s = std::string(line.Part1) + std::string(line.Part2);
co_await ws.SendText(std::string_view(s));
}
co_await receiver;
TWebSocket API
| Method | Description |
|---|---|
co_await ws.Connect(host, path) |
HTTP Upgrade handshake |
co_await ws.SendText(sv) |
Send text frame (auto-masked per RFC 6455) |
co_await ws.ReceiveText() |
Receive next text frame; string_view valid until next call |
Client-side only. Binary frames not supported.