Skip to content
/ wspp Public

Modern, Async, Non-Blocking, zero-dependency C++20 RFC 6455 Compliant WebSocket client & server, cross-platform, single-header, WS/WSS support.

License

Notifications You must be signed in to change notification settings

pinwhell/wspp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wspp

C++20 License Build Autobahn

 __      __  _____________________________ 
/  \    /  \/   _____/\______   \______   \
\   \/\/   /\_____  \  |     ___/|     ___/
 \        / /        \ |    |    |    |    
  \__/\  / /_______  / |____|    |____|    
       \/          \/                      

Modern, header-only WebSocket library for C++20
Build WebSocket clients & servers. RFC Compliant, Async, non-blocking, cross-platform, zero dependencies (optional OpenSSL for WSS).


Why wspp?

  • ✅ Header-only → drop-in, no linking hassle
  • ✅ Supports WS & WSS → secure
  • ✅ RFC 6455 Compliant → Passing all Autobahn tests
  • ✅ Fully async/reactor → handle multiple connections efficiently
  • ✅ Cross-platform → Windows & Linux
  • ✅ Minimal and modern → C++20 clean API

Autobahn TestSuite (RFC 6455 Compliance)


Quick Client Example (1 minute to run):

#include <wspp/wspp.h>
#include <iostream>

int main() {
    wspp::wss_client c;
    // or wspp::ws_client for ws://
    c.connect("wss://echo.websocket.org/");

    c.on_message([](wspp::message_view msg) {
        std::cout << "Received: " << msg.text() << "\n";
        c.close();
    });

    c.on_close([](auto) {
        std::cout << "ws closed\n";
    });

    // or 
    // c.on_close([](wspp::close_event e) {
    //    // e.reason: aborted, normal, remote
    //    if (e.code)
    //        std::cout << "closed " << int(*e.code) << "\n";
    // });

    c.on_open([&c] {
        c.send("Hello wspp!");
    });
    
    c.run();
}
Output:
Received: Hello wspp!
ws closed

Quick Server Example (1 minute to run):

#include <wspp/wspp.h>
#include <iostream>

int main() {
    wspp::wss_server ws({ .cert = "server.crt", .key = "server.key" });
    // or wspp::ws_server for ws://
    ws.on_connection([](/*wspp::wss_server<>::connection_ptr or*/ auto c) {
        c->on_message([c](wspp::message_view msg) {
            if (msg.is_text())
                std::cout << msg.text() << '\n';
            if (msg.is_binary())
                std::cout << "Size: " << msg.binary().size() << '\n';
            c->send(msg); // Echo
            });

        c->on_close([](/*wspp::close_event or*/ auto e) {
            // e.reason: aborted, normal, remote
            std::cout << "client closed";
            if (e.code)
                std::cout << " with code " << int(*e.code);
            std::cout << '\n';
            });
        });
    ws.listen(8080);
    ws.run();
}

Chat Example (With pub/subs)

#include <wspp/wspp.h>
#include <iostream>
#include <format>

int main()
{
    wspp::wss_server sv({ .cert = "server.crt", .key = "server.key" });
    // or wspp::ws_server for ws://

    sv.on_connection([&sv](auto conn) {
        conn->on_message([&sv, conn](wspp::message_view msg) {
            if (!msg.is_text()) return;
            auto text = msg.text();

            if (text.starts_with("/sub ")) {
                auto room = text.substr(5);
                sv.subscribe(conn, room);
                return;
            }

            if (text.starts_with("/unsub ")) {
                auto room = text.substr(7);
                sv.unsubscribe(conn, room);
                return;
            }

            if (text.starts_with("/message ")) {
                auto space = text.find(' ', 9);
                auto room = text.substr(9, space - 9);
                auto msg = text.substr(space + 1);
                sv.publish(room, std::format("{}:{}: {}", room, conn->id(), msg));
                return;
            }
            });
        });

    sv.listen(8080);
    sv.run();
}

Mini Chat Server Example(Simpler):

#include <wspp/wspp.h>
#include <iostream>
#include <format>

int main() {
    wspp::ws_server ws;
    // or wspp::wss_server for wss://
    ws.on_connection([&ws](auto c) {
        ws.broadcast_except(c, 
            std::format("{}:: joined.", c->id()));

        c->on_message([&ws, c](wspp::message_view msg) {
            if (!msg.is_text()) return;
            ws.broadcast_except(c, 
                std::format("{}: {}", 
                    c->id(), msg.text()));
            });

        c->on_close([c, &ws](wspp::close_event e) {
            ws.broadcast_except(c, std::format(
                "{}:: left.", c->id()));
            });
        });
    ws.listen(8080);
    ws.run();
}

Features

wspp is designed to make WebSockets in C++ effortless, modern, and reliable.

  • Header-only
    No linking, no build pain. Just include and go.

  • 🔒 WS & WSS support
    Secure connections via OpenSSL (optional). Works out-of-the-box for public WebSocket endpoints.

  • Asynchronous / non-blocking
    Efficient, single-threaded event loop; supports multiple connections with minimal overhead.

  • 🌍 Cross-platform
    Runs on Windows and Linux without platform-specific changes.

  • 🧩 Flexible API

    • ws_client for plain WebSockets Client
    • ws_server for plain WebSockets Server
    • wss_client for secure WebSockets Client
    • wss_server for secure WebSockets Server
    • Reactor pattern built-in for handling multiple streams
  • 🛡 RFC-compliant
    Handles: fragmentation, masking, ping/pong, close codes, UTF-8 validation, handshake validation.

  • 💡 Modern C++20 design
    Concepts, std::string_view, std::chrono, lambdas for callbacks, clean and minimal API.

  • 📦 Drop-in examples
    Ready-to-run examples for Binance, echo servers, and more.

  • 🔧 Developer-friendly
    Optional playground, tests, examples. Configure via CMake options:

    • WSPP_BUILD_TESTS
    • WSPP_BUILD_EXAMPLES
    • WSPP_BUILD_PLAYGROUND

Installation

wspp is CMake-friendly and header-only—getting started is effortless.

Requirements

  • C++20 compiler (GCC ≥10, Clang ≥11, MSVC ≥2019)
  • CMake ≥3.16
  • OpenSSL (optional, for wss:// support)

Using CMake

  1. Clone the repository
git clone https://github.com/pinwhell/wspp.git
cd wspp
  1. Configure the project
mkdir build && cd build
cmake .. -DWSPP_USE_OPENSSL=ON   # Enable WSS if you have OpenSSL
cmake --build .
  1. Install (optional)
cmake --install .

This will install headers to include/ and CMake targets to lib/cmake/wspp.

Minimal Header-only Usage

#include <wspp/wspp.h>

Just include and start coding—no linking, no setup.

CMake Integration

Add to your project:

find_package(wspp REQUIRED)
target_link_libraries(your_target PRIVATE wspp::wspp)

License

wspp is released under the MIT License.

About

Modern, Async, Non-Blocking, zero-dependency C++20 RFC 6455 Compliant WebSocket client & server, cross-platform, single-header, WS/WSS support.

Resources

License

Stars

Watchers

Forks

Packages

No packages published