You've already forked cpp-httplib
							
							
		
			
				
	
	
		
			103 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <atomic>
 | |
| #include <chrono>
 | |
| #include <condition_variable>
 | |
| #include <httplib.h>
 | |
| #include <iostream>
 | |
| #include <mutex>
 | |
| #include <sstream>
 | |
| #include <thread>
 | |
| 
 | |
| using namespace httplib;
 | |
| using namespace std;
 | |
| 
 | |
| class EventDispatcher {
 | |
| public:
 | |
|   EventDispatcher() {
 | |
|   }
 | |
| 
 | |
|   void wait_event(DataSink *sink) {
 | |
|     unique_lock<mutex> lk(m_);
 | |
|     int id = id_;
 | |
|     cv_.wait(lk, [&] { return cid_ == id; });
 | |
|     if (sink->is_writable()) { sink->write(message_.data(), message_.size()); }
 | |
|   }
 | |
| 
 | |
|   void send_event(const string &message) {
 | |
|     lock_guard<mutex> lk(m_);
 | |
|     cid_ = id_++;
 | |
|     message_ = message;
 | |
|     cv_.notify_all();
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   mutex m_;
 | |
|   condition_variable cv_;
 | |
|   atomic_int id_{0};
 | |
|   atomic_int cid_{-1};
 | |
|   string message_;
 | |
| };
 | |
| 
 | |
| const auto html = R"(
 | |
| <!DOCTYPE html>
 | |
| <html lang="en">
 | |
| <head>
 | |
| <meta charset="UTF-8">
 | |
| <title>SSE demo</title>
 | |
| </head>
 | |
| <body>
 | |
| <script>
 | |
| const ev1 = new EventSource("event1");
 | |
| ev1.onmessage = function(e) {
 | |
|   console.log('ev1', e.data);
 | |
| }
 | |
| const ev2 = new EventSource("event2");
 | |
| ev2.onmessage = function(e) {
 | |
|   console.log('ev2', e.data);
 | |
| }
 | |
| </script>
 | |
| </body>
 | |
| </html>
 | |
| )";
 | |
| 
 | |
| int main(void) {
 | |
|   EventDispatcher ed;
 | |
| 
 | |
|   Server svr;
 | |
| 
 | |
|   svr.Get("/", [&](const Request & /*req*/, Response &res) {
 | |
|     res.set_content(html, "text/html");
 | |
|   });
 | |
| 
 | |
|   svr.Get("/event1", [&](const Request & /*req*/, Response &res) {
 | |
|     cout << "connected to event1..." << endl;
 | |
|     res.set_chunked_content_provider("text/event-stream",
 | |
|                                      [&](size_t /*offset*/, DataSink &sink) {
 | |
|                                        ed.wait_event(&sink);
 | |
|                                        return true;
 | |
|                                      });
 | |
|   });
 | |
| 
 | |
|   svr.Get("/event2", [&](const Request & /*req*/, Response &res) {
 | |
|     cout << "connected to event2..." << endl;
 | |
|     res.set_chunked_content_provider("text/event-stream",
 | |
|                                      [&](size_t /*offset*/, DataSink &sink) {
 | |
|                                        ed.wait_event(&sink);
 | |
|                                        return true;
 | |
|                                      });
 | |
|   });
 | |
| 
 | |
|   thread t([&] {
 | |
|     int id = 0;
 | |
|     while (true) {
 | |
|       this_thread::sleep_for(chrono::seconds(1));
 | |
|       cout << "send event: " << id << std::endl;
 | |
|       std::stringstream ss;
 | |
|       ss << "data: " << id << "\n\n";
 | |
|       ed.send_event(ss.str());
 | |
|       id++;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   svr.listen("localhost", 1234);
 | |
| }
 |