| #include <httplib.h> |
| #include <iostream> |
| |
| using namespace httplib; |
| |
| const auto html = R"HTML( |
| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>WebSocket Demo</title> |
| <style> |
| body { font-family: monospace; margin: 2em; } |
| #log { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 8px; } |
| .controls { margin: 8px 0; } |
| button { margin-right: 4px; } |
| </style> |
| </head> |
| <body> |
| <h1>WebSocket Demo</h1> |
| <p>Server accepts subprotocols: <b>echo</b>, <b>chat</b> (or none)</p> |
| |
| <div class="controls"> |
| <label>Subprotocols: </label> |
| <input id="protos" type="text" value="echo, chat" placeholder="leave empty for none" /> |
| <button onclick="doConnect()">Connect</button> |
| <button onclick="doDisconnect()">Disconnect</button> |
| </div> |
| |
| <div class="controls"> |
| <input id="msg" type="text" placeholder="Type a message..." /> |
| <button onclick="doSend()">Send</button> |
| </div> |
| |
| <div class="controls"> |
| <button onclick="startAuto()">Start Auto (1s)</button> |
| <button onclick="stopAuto()">Stop Auto</button> |
| <span id="auto-status"></span> |
| </div> |
| |
| <pre id="log"></pre> |
| |
| <script> |
| var sock = null; |
| var logEl = document.getElementById("log"); |
| var statusEl = document.getElementById("auto-status"); |
| var timer = null; |
| var seq = 0; |
| |
| function appendLog(text) { |
| logEl.textContent += text + "\n"; |
| logEl.scrollTop = logEl.scrollHeight; |
| } |
| |
| function doConnect() { |
| if (sock && sock.readyState <= 1) { sock.close(); } |
| var input = document.getElementById("protos").value.trim(); |
| var protocols = input ? input.split(/\s*,\s*/).filter(Boolean) : []; |
| sock = new WebSocket("ws://" + location.host + "/ws", protocols); |
| appendLog("[connecting] proposed: " + (protocols.length ? protocols.join(", ") : "(none)")); |
| sock.onopen = function() { appendLog("[connected] subprotocol: " + (sock.protocol || "(none)")); }; |
| sock.onclose = function() { appendLog("[disconnected]"); stopAuto(); }; |
| sock.onmessage = function(e) { appendLog("< " + e.data); }; |
| } |
| |
| function doDisconnect() { |
| if (sock) { sock.close(); } |
| } |
| |
| function doSend() { |
| var input = document.getElementById("msg"); |
| if (!sock || sock.readyState !== 1 || input.value === "") return; |
| sock.send(input.value); |
| appendLog("> " + input.value); |
| input.value = ""; |
| } |
| |
| function startAuto() { |
| if (timer || !sock || sock.readyState !== 1) return; |
| seq = 0; |
| statusEl.textContent = "running..."; |
| timer = setInterval(function() { |
| if (!sock || sock.readyState !== 1) { stopAuto(); return; } |
| var msg = "auto #" + seq++; |
| sock.send(msg); |
| appendLog("> " + msg); |
| }, 1000); |
| } |
| |
| function stopAuto() { |
| if (timer) { clearInterval(timer); timer = null; } |
| statusEl.textContent = ""; |
| } |
| |
| document.getElementById("msg").addEventListener("keydown", function(e) { |
| if (e.key === "Enter") doSend(); |
| }); |
| |
| doConnect(); |
| </script> |
| </body> |
| </html> |
| )HTML"; |
| |
| int main(void) { |
| Server svr; |
| |
| svr.Get("/", [&](const Request & /*req*/, Response &res) { |
| res.set_content(html, "text/html"); |
| }); |
| |
| svr.WebSocket( |
| "/ws", |
| [](const Request &req, ws::WebSocket &ws) { |
| std::cout << "WebSocket connected from " << req.remote_addr |
| << std::endl; |
| |
| std::string msg; |
| while (ws.read(msg)) { |
| std::cout << "Received: " << msg << std::endl; |
| ws.send("echo: " + msg); |
| } |
| |
| std::cout << "WebSocket disconnected" << std::endl; |
| }, |
| [](const std::vector<std::string> &protocols) -> std::string { |
| for (const auto &p : protocols) { |
| if (p == "echo" || p == "chat") { return p; } |
| } |
| return ""; |
| }); |
| |
| std::cout << "Listening on http://localhost:8080" << std::endl; |
| svr.listen("localhost", 8080); |
| } |