Skip to content

Repository files navigation

WebsocketProxy

C++20License: MIT

A high-performance C++ framework that enables multiple clients to share a single WebSocket connection through efficient inter-process communication (IPC) using shared memory queues.

Overview

WebsocketProxy solves the problem of connection limitations by allowing multiple client applications to share a single WebSocket connection. Originally designed for Alpaca Markets, which restricts accounts to one WebSocket connection, it enables multiple trading strategies to receive real-time market data simultaneously.

Key Features:

  • Zero-Copy IPC: Lock-free shared memory queues for high-performance communication
  • Protocol-Agnostic: Transparent message pass-through works with any WebSocket API
  • Automatic Lifecycle Management: Server spawns on first client connection and terminates when all clients disconnect
  • Header-Only Client: Lightweight, easy-to-integrate client library
  • Multi-Platform: Windows support with cross-platform design
  • Resource Efficient: Single WebSocket connection serves unlimited clients

Architecture

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client 1 │ │ Client 2 │ │ Client N │
│ │ │ │ │ │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ Shared Memory Queues (IPC) │
└───────────────┬───────────────────────┘
│
┌────────▼────────┐
│ Proxy Server │
│ (websocket_ │
│ proxy.exe) │
└────────┬────────┘
│
│ Single WebSocket
│
┌────────▼────────┐
│ Remote Server │
│ (e.g., Alpaca) │
└─────────────────┘

Components

  1. Proxy Server (websocket_proxy.exe)

    • Maintains single WebSocket connection to remote server
    • Manages IPC via lock-free shared memory queues
    • Automatically spawned by first client connection
    • Routes messages between clients and remote server
    • Terminates when all clients disconnect
  2. Proxy Client (Header-only library)

    • Lightweight client library for your applications
    • Derives from WebsocketProxyCallback interface
    • Handles spawning and communication with proxy server
    • Provides async/sync WebSocket operations
    • Automatic heartbeat and reconnection handling

Quick Start

Installation

Download the latest release from the releases page, extract it, and copy the contents to your project:

# Extract release
unzip websocket_proxy_v1.1.1.1.zip
# Copy headers to your project
cp -r include /path/to/your/project/
# Copy proxy server executable
cp bin/websocket_proxy.exe /path/to/your/project/bin/

Usage Example

  1. Implement the callback interface:
#include<websocket_proxy/websocket_proxy_client.h>classMyWebSocketClient : publicwebsocket_proxy::WebsocketProxyCallback {
public:voidonWebsocketProxyServerDisconnected() override {
// Handle proxy server disconnect
}
voidonWebsocketOpened(uint64_t id) override {
// WebSocket connection established
std::cout << "Connected: " << id << std::endl;
}
voidonWebsocketClosed(uint64_t id) override {
// WebSocket connection closed
}
voidonWebsocketError(uint64_t id, constchar* err, uint32_t len) override {
// Handle WebSocket errors
std::cerr << "Error: " << std::string(err, len) << std::endl;
}
voidonWebsocketData(uint64_t id, constchar* data, uint32_t len, uint32_t remaining) override {
// Process incoming data
std::string message(data, len);
std::cout << "Received: " << message << std::endl;
}
};
  1. Create and use the client:
#include<websocket_proxy/websocket_proxy_client.h>intmain() {
MyWebSocketClient callback;
// Initialize client with callback and proxy server path
websocket_proxy::WebsocketProxyClient client(
&callback,
"MyClient", // Client name"./bin/websocket_proxy.exe"// Proxy server path
);
// Open WebSocket connectionauto [id, is_new] = client.openWebSocket(
"wss://stream.data.alpaca.markets/v2/iex", // WebSocket URL"your_api_key"// API key (optional)
);
if (id) {
// Send messages
std::string msg = R"({"action":"subscribe","bars":["AAPL"]})";
client.send(id, msg.c_str(), msg.size());
// Keep running...std::this_thread::sleep_for(std::chrono::seconds(60));
// Close connection
client.closeWebSocket(id);
}
return0;
}

For a complete example, see the Alpaca WebSocket client in the example/ directory.

Building From Source

Requirements

  • C++20 compatible compiler (MSVC 2019+, GCC 10+, Clang 12+)
  • CMake 3.16 or higher
  • vcpkg for dependency management
  • Dependencies:
    • Boost.Beast (WebSocket client)
    • OpenSSL (TLS/SSL support)
    • slick_logger (automatically fetched)
    • slick_queue (automatically fetched)

Setup vcpkg

# Clone and bootstrap vcpkg
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
# Windows
./bootstrap-vcpkg.bat
# Linux/macOS
./bootstrap-vcpkg.sh
# Install dependencies
./vcpkg install boost-beast:x64-windows-static
./vcpkg install openssl:x64-windows-static

Build Steps

# Clone repository
git clone https://github.com/kzhdev/websocket_proxy.git
cd websocket_proxy
# Configure with CMake (Windows example)
cmake -S . -B build \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_BUILD_TYPE=Release
# Build
cmake --build ./build --config Release -j
# Output will be in build/bin/Release/websocket_proxy.exe# Headers in build/dist/include/

Build Options

# Build without example
cmake -S . -B build -DBUILD_EXAMPLE=OFF
# Debug build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
# Create distribution package (Release only)# Automatically creates websocket_proxy_<version>.zip in build/dist/
cmake --build ./build --config Release

Install

# Install to system (optional)
cmake --install ./build --prefix /usr/local

API Reference

WebsocketProxyCallback Interface

Implement this interface to handle WebSocket events:

classWebsocketProxyCallback {
public:virtual~WebsocketProxyCallback() = default;
// Called when proxy server disconnectsvirtualvoidonWebsocketProxyServerDisconnected() = 0;
// Called when WebSocket connection opensvirtualvoidonWebsocketOpened(uint64_t id) = 0;
// Called when WebSocket connection closesvirtualvoidonWebsocketClosed(uint64_t id) = 0;
// Called on WebSocket errorsvirtualvoidonWebsocketError(uint64_t id, constchar* err, uint32_t len) = 0;
// Called when data is received// remaining: bytes remaining in current message (for fragmented messages)virtualvoidonWebsocketData(uint64_t id, constchar* data, uint32_t len, uint32_t remaining) = 0;
// Optional: Logging callbacksvirtualvoidlogError(std::function<std::string()>&&) {}
virtualvoidlogWarning(std::function<std::string()>&&) {}
virtualvoidlogInfo(std::function<std::string()>&&) {}
virtualvoidlogDebug(std::function<std::string()>&&) {}
};

WebsocketProxyClient Methods

// ConstructorWebsocketProxyClient(
WebsocketProxyCallback* callback,
std::string&& name, // Client identifier
std::string&& proxy_exe_path // Path to websocket_proxy.exe
);
// Open WebSocket (synchronous) - returns (connection_id, is_new_connection)
std::pair<uint64_t, bool> openWebSocket(
const std::string& url,
const std::string& api_key = ""
);
// Open WebSocket (asynchronous)boolopenWebSocketAsync(
const std::string& url,
const std::string& api_key = ""
);
// Close WebSocket (id=0 closes all)boolcloseWebSocket(uint64_t id = 0);
// Send data to WebSocketvoidsend(uint64_t id, constchar* msg, uint32_t len);
// Subscribe to symbol (for trading APIs)boolsubscribe(
uint64_t id,
const std::string& symbol,
constchar* subscription_request,
uint32_t request_len,
SubscriptionType type,
bool& existing
);
// Unsubscribe from symbolboolunsubscribe(
uint64_t id,
const std::string& symbol,
constchar* unsubscription_request,
uint32_t request_len
);
// Set logging levelboolsetLogLevel(LogLevel::level_enum level);
// Get server process IDuint64_tserverId() constnoexcept;

Performance

  • Zero-copy IPC: Shared memory queues eliminate data copying between processes
  • Lock-free: Wait-free algorithms for high-throughput communication
  • Low latency: Optimized message routing with minimal overhead
  • Scalable: Supports unlimited clients with constant memory per client

Use Cases

  • Trading Systems: Share market data WebSocket across multiple strategies
  • Real-time Data: Multiple consumers for single data stream
  • API Rate Limiting: Multiplex API connections with connection limits
  • Resource Optimization: Reduce connection overhead in microservices
  • Development/Testing: Test multiple clients with single connection

Troubleshooting

Server fails to start

  • Ensure websocket_proxy.exe path is correct
  • Check Windows Defender/Firewall isn't blocking execution
  • Verify shared memory permissions

Connection timeout

  • Increase timeout in waitForResponse() calls
  • Check network connectivity to remote server
  • Verify WebSocket URL is correct

Memory issues

  • Monitor shared queue sizes for memory leaks
  • Ensure proper cleanup on client disconnect
  • Check for deadlocks in message handling

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License. See the LICENSE file for details.

Acknowledgments

Support


Version: 1.1.1.1 Author: Kun Zhao Copyright: © 2024-2025

About

A C++ WebSocket Proxy Framework

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages