# WebSocket

cpp-httplib supports WebSocket as well. Unlike HTTP request/response, WebSocket lets the server and client exchange messages in both directions. It's great for chat apps and real-time notifications.

Let's build an echo server and client right away.

## Echo Server

Here's an echo server that sends back whatever message it receives.

    #include "httplib.h"
    #include <iostream>

    int main() {
        httplib::Server svr;

        svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
            std::string msg;
            while (ws.read(msg)) {
                ws.send(msg);  // Send back the received message as-is
            }
        });

        std::cout << "Listening on port 8080..." << std::endl;
        svr.listen("0.0.0.0", 8080);
    }

    #include "httplib.h"
    #include <iostream>

    int main() {
        httplib::Server svr;

        svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
            std::string msg;
            while (ws.read(msg)) {
                ws.send(msg);  // Send back the received message as-is
            }
        });

        std::cout << "Listening on port 8080..." << std::endl;
        svr.listen("0.0.0.0", 8080);
    }

You register a WebSocket handler with `svr.WebSocket()`. It works just like `svr.Get()` and `svr.Post()` from Chapter 3.

Inside the handler, `ws.read(msg)` waits for a message. When the connection closes, `read()` returns `false`, so the loop exits. `ws.send(msg)` sends a message back.

## Connecting from a Client

Let's connect to the server using `httplib::ws::WebSocketClient`.

    #include "httplib.h"
    #include <iostream>

    int main() {
        httplib::ws::WebSocketClient client("ws://localhost:8080/ws");

        if (!client.connect()) {
            std::cout << "Connection failed" << std::endl;
            return 1;
        }

        // Send a message
        client.send("Hello, WebSocket!");

        // Receive a response from the server
        std::string msg;
        if (client.read(msg)) {
            std::cout << msg << std::endl;  // Hello, WebSocket!
        }

        client.close();
    }

    #include "httplib.h"
    #include <iostream>

    int main() {
        httplib::ws::WebSocketClient client("ws://localhost:8080/ws");

        if (!client.connect()) {
            std::cout << "Connection failed" << std::endl;
            return 1;
        }

        // Send a message
        client.send("Hello, WebSocket!");

        // Receive a response from the server
        std::string msg;
        if (client.read(msg)) {
            std::cout << msg << std::endl;  // Hello, WebSocket!
        }

        client.close();
    }

Pass a URL in `ws://host:port/path` format to the constructor. Call `connect()` to start the connection, then use `send()` and `read()` to exchange messages.

## Text and Binary

WebSocket has two types of messages: text and binary. You can tell them apart by the return value of `read()`.

    svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
        std::string msg;
        httplib::ws::ReadResult ret;
        while ((ret = ws.read(msg))) {
            if (ret == httplib::ws::Binary) {
                ws.send(msg.data(), msg.size());  // Send as binary
            } else {
                ws.send(msg);  // Send as text
            }
        }
    });

    svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
        std::string msg;
        httplib::ws::ReadResult ret;
        while ((ret = ws.read(msg))) {
            if (ret == httplib::ws::Binary) {
                ws.send(msg.data(), msg.size());  // Send as binary
            } else {
                ws.send(msg);  // Send as text
            }
        }
    });

- `ws.send(const std::string &)` — sends as a text message
- `ws.send(const char *, size_t)` — sends as a binary message

The client-side API is the same.

## Accessing Request Information

You can read HTTP request information from the handshake through the first argument `req` in the handler. This is handy for checking authentication tokens.

    svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) {
        auto token = req.get_header_value("Authorization");
        if (token.empty()) {
            ws.close(httplib::ws::CloseStatus::PolicyViolation, "unauthorized");
            return;
        }

        std::string msg;
        while (ws.read(msg)) {
            ws.send(msg);
        }
    });

    svr.WebSocket("/ws", [](const httplib::Request &req, httplib::ws::WebSocket &ws) {
        auto token = req.get_header_value("Authorization");
        if (token.empty()) {
            ws.close(httplib::ws::CloseStatus::PolicyViolation, "unauthorized");
            return;
        }

        std::string msg;
        while (ws.read(msg)) {
            ws.send(msg);
        }
    });

## Using WSS

WebSocket over HTTPS (WSS) is also supported. On the server side, just register a WebSocket handler on `httplib::SSLServer`.

    httplib::SSLServer svr("cert.pem", "key.pem");

    svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
        std::string msg;
        while (ws.read(msg)) {
            ws.send(msg);
        }
    });

    svr.listen("0.0.0.0", 8443);

    httplib::SSLServer svr("cert.pem", "key.pem");

    svr.WebSocket("/ws", [](const httplib::Request &, httplib::ws::WebSocket &ws) {
        std::string msg;
        while (ws.read(msg)) {
            ws.send(msg);
        }
    });

    svr.listen("0.0.0.0", 8443);

On the client side, use the `wss://` scheme.

    httplib::ws::WebSocketClient client("wss://localhost:8443/ws");

    httplib::ws::WebSocketClient client("wss://localhost:8443/ws");

## Next Steps

Now you know the basics of WebSocket. This wraps up the Tour.

The next page gives you a summary of features we didn't cover in the Tour.

Next: What's Next