1
0

wsecho.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <httplib.h>
  2. #include <iostream>
  3. using namespace httplib;
  4. const auto html = R"HTML(
  5. <!DOCTYPE html>
  6. <html lang="en">
  7. <head>
  8. <meta charset="UTF-8">
  9. <title>WebSocket Demo</title>
  10. <style>
  11. body { font-family: monospace; margin: 2em; }
  12. #log { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 8px; }
  13. .controls { margin: 8px 0; }
  14. button { margin-right: 4px; }
  15. </style>
  16. </head>
  17. <body>
  18. <h1>WebSocket Demo</h1>
  19. <p>Server accepts subprotocols: <b>echo</b>, <b>chat</b> (or none)</p>
  20. <div class="controls">
  21. <label>Subprotocols: </label>
  22. <input id="protos" type="text" value="echo, chat" placeholder="leave empty for none" />
  23. <button onclick="doConnect()">Connect</button>
  24. <button onclick="doDisconnect()">Disconnect</button>
  25. </div>
  26. <div class="controls">
  27. <input id="msg" type="text" placeholder="Type a message..." />
  28. <button onclick="doSend()">Send</button>
  29. </div>
  30. <div class="controls">
  31. <button onclick="startAuto()">Start Auto (1s)</button>
  32. <button onclick="stopAuto()">Stop Auto</button>
  33. <span id="auto-status"></span>
  34. </div>
  35. <pre id="log"></pre>
  36. <script>
  37. var sock = null;
  38. var logEl = document.getElementById("log");
  39. var statusEl = document.getElementById("auto-status");
  40. var timer = null;
  41. var seq = 0;
  42. function appendLog(text) {
  43. logEl.textContent += text + "\n";
  44. logEl.scrollTop = logEl.scrollHeight;
  45. }
  46. function doConnect() {
  47. if (sock && sock.readyState <= 1) { sock.close(); }
  48. var input = document.getElementById("protos").value.trim();
  49. var protocols = input ? input.split(/\s*,\s*/).filter(Boolean) : [];
  50. sock = new WebSocket("ws://" + location.host + "/ws", protocols);
  51. appendLog("[connecting] proposed: " + (protocols.length ? protocols.join(", ") : "(none)"));
  52. sock.onopen = function() { appendLog("[connected] subprotocol: " + (sock.protocol || "(none)")); };
  53. sock.onclose = function() { appendLog("[disconnected]"); stopAuto(); };
  54. sock.onmessage = function(e) { appendLog("< " + e.data); };
  55. }
  56. function doDisconnect() {
  57. if (sock) { sock.close(); }
  58. }
  59. function doSend() {
  60. var input = document.getElementById("msg");
  61. if (!sock || sock.readyState !== 1 || input.value === "") return;
  62. sock.send(input.value);
  63. appendLog("> " + input.value);
  64. input.value = "";
  65. }
  66. function startAuto() {
  67. if (timer || !sock || sock.readyState !== 1) return;
  68. seq = 0;
  69. statusEl.textContent = "running...";
  70. timer = setInterval(function() {
  71. if (!sock || sock.readyState !== 1) { stopAuto(); return; }
  72. var msg = "auto #" + seq++;
  73. sock.send(msg);
  74. appendLog("> " + msg);
  75. }, 1000);
  76. }
  77. function stopAuto() {
  78. if (timer) { clearInterval(timer); timer = null; }
  79. statusEl.textContent = "";
  80. }
  81. document.getElementById("msg").addEventListener("keydown", function(e) {
  82. if (e.key === "Enter") doSend();
  83. });
  84. doConnect();
  85. </script>
  86. </body>
  87. </html>
  88. )HTML";
  89. int main(void) {
  90. Server svr;
  91. svr.Get("/", [&](const Request & /*req*/, Response &res) {
  92. res.set_content(html, "text/html");
  93. });
  94. svr.WebSocket(
  95. "/ws",
  96. [](const Request &req, ws::WebSocket &ws) {
  97. std::cout << "WebSocket connected from " << req.remote_addr
  98. << std::endl;
  99. std::string msg;
  100. while (ws.read(msg)) {
  101. std::cout << "Received: " << msg << std::endl;
  102. ws.send("echo: " + msg);
  103. }
  104. std::cout << "WebSocket disconnected" << std::endl;
  105. },
  106. [](const std::vector<std::string> &protocols) -> std::string {
  107. for (const auto &p : protocols) {
  108. if (p == "echo" || p == "chat") { return p; }
  109. }
  110. return "";
  111. });
  112. std::cout << "Listening on http://localhost:8080" << std::endl;
  113. svr.listen("localhost", 8080);
  114. }