ssesvr.cc 2.3 KB

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