ssesvr.cc 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <atomic>
  2. #include <chrono>
  3. #include <condition_variable>
  4. #include <httplib.h>
  5. #include <iostream>
  6. #include <mutex>
  7. #include <sstream>
  8. #include <thread>
  9. using namespace httplib;
  10. using namespace std;
  11. class EventDispatcher {
  12. public:
  13. EventDispatcher() {}
  14. void wait_event(DataSink *sink) {
  15. unique_lock<mutex> lk(m_);
  16. int id = id_;
  17. cv_.wait(lk, [&] { return cid_ == id; });
  18. sink->write(message_.data(), message_.size());
  19. }
  20. void send_event(const string &message) {
  21. lock_guard<mutex> lk(m_);
  22. cid_ = id_++;
  23. message_ = message;
  24. cv_.notify_all();
  25. }
  26. private:
  27. mutex m_;
  28. condition_variable cv_;
  29. atomic_int id_{0};
  30. atomic_int cid_{-1};
  31. string message_;
  32. };
  33. const auto html = R"(
  34. <!DOCTYPE html>
  35. <html lang="en">
  36. <head>
  37. <meta charset="UTF-8">
  38. <title>SSE demo</title>
  39. </head>
  40. <body>
  41. <script>
  42. const ev1 = new EventSource("event1");
  43. ev1.onmessage = function(e) {
  44. console.log('ev1', e.data);
  45. }
  46. const ev2 = new EventSource("event2");
  47. ev2.onmessage = function(e) {
  48. console.log('ev2', e.data);
  49. }
  50. </script>
  51. </body>
  52. </html>
  53. )";
  54. int main(void) {
  55. EventDispatcher ed;
  56. Server svr;
  57. svr.Get("/", [&](const Request & /*req*/, Response &res) {
  58. res.set_content(html, "text/html");
  59. });
  60. svr.Get("/event1", [&](const Request & /*req*/, Response &res) {
  61. cout << "connected to event1..." << endl;
  62. res.set_chunked_content_provider("text/event-stream",
  63. [&](size_t /*offset*/, DataSink &sink) {
  64. ed.wait_event(&sink);
  65. return true;
  66. });
  67. });
  68. svr.Get("/event2", [&](const Request & /*req*/, Response &res) {
  69. cout << "connected to event2..." << endl;
  70. res.set_chunked_content_provider("text/event-stream",
  71. [&](size_t /*offset*/, DataSink &sink) {
  72. ed.wait_event(&sink);
  73. return true;
  74. });
  75. });
  76. thread t([&] {
  77. int id = 0;
  78. while (true) {
  79. this_thread::sleep_for(chrono::seconds(1));
  80. cout << "send event: " << id << std::endl;
  81. std::stringstream ss;
  82. ss << "data: " << id << "\n\n";
  83. ed.send_event(ss.str());
  84. id++;
  85. }
  86. });
  87. svr.listen("localhost", 1234);
  88. }