基于Boost.Beast的WebSocket/HTTP混合服务器实现全客户端消息广播求助
Hey there! I’ve tinkered with the advanced_server.cpp example before, so I can help you add that broadcast functionality you’re looking for. Here’s a step-by-step breakdown tailored to your setup:
1. Maintain a Thread-Safe List of Active WebSocket Sessions
First, you need a way to track all connected WebSocket clients (since HTTP is short-lived, broadcast typically targets long-lived WebSocket connections).
Add a container and mutex to your server class to manage these sessions:
#include <set> #include <mutex> class server { // ... existing members from advanced_server.cpp ... std::set<std::shared_ptr<websocket_session>> sessions_; std::mutex sessions_mutex_; public: // Add a new session to the tracking list void add_session(std::shared_ptr<websocket_session> session) { std::lock_guard<std::mutex> lock(sessions_mutex_); sessions_.insert(session); } // Remove a session when it closes void remove_session(std::shared_ptr<websocket_session> session) { std::lock_guard<std::mutex> lock(sessions_mutex_); sessions_.erase(session); } };
2. Update WebSocket Sessions to Register/Unregister
Modify your websocket_session class to automatically add itself to the server's list on creation, and remove itself when it’s destroyed. Using shared_ptr ensures the session stays alive while it’s registered:
class websocket_session : public std::enable_shared_from_this<websocket_session> { server& server_; // ... existing members ... public: websocket_session(server& s, /* other constructor params */) : server_(s) { // Register ourselves with the server when we start server_.add_session(shared_from_this()); } ~websocket_session() { // Unregister when the session is destroyed server_.remove_session(shared_from_this()); } // ... existing methods from advanced_server.cpp ... };
3. Implement the Broadcast Logic
Add a message queue to each websocket_session to handle asynchronous sends safely (since you can’t write to a WebSocket concurrently), then add a broadcast method to the server:
First, update the websocket_session with a queue and send logic:
class websocket_session { // ... existing members ... std::queue<std::string> send_queue_; bool is_sending_ = false; std::mutex queue_mutex_; // Helper to trigger async sends from the queue void do_send() { std::lock_guard<std::mutex> lock(queue_mutex_); if (is_sending_ || send_queue_.empty()) { return; } is_sending_ = true; ws_.async_write( boost::asio::buffer(send_queue_.front()), std::bind( &websocket_session::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2 ) ); } public: // Public method to queue a message for sending void send(std::string message) { std::lock_guard<std::mutex> lock(queue_mutex_); send_queue_.push(std::move(message)); do_send(); } // Update on_write to process the next message in the queue void on_write(boost::system::error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); std::lock_guard<std::mutex> lock(queue_mutex_); send_queue_.pop(); is_sending_ = false; if (!ec) { do_send(); // Send next message if queue isn't empty } else { // Handle errors gracefully (e.g., close the session) fail(ec, "write"); } } // ... existing methods ... };
Then add the broadcast method to the server class:
class server { // ... existing members ... public: void broadcast(std::string message) { std::lock_guard<std::mutex> lock(sessions_mutex_); for (auto& session : sessions_) { session->send(message); } } };
4. Trigger Broadcast Wherever Needed
Now you can call server::broadcast() from any part of your code—like an HTTP handler that triggers a server-wide update, or a WebSocket message that needs to be shared with all clients:
// Example: Broadcast from an HTTP request handler void handle_http_request(/* request/response params */) { // ... process the HTTP request ... server_.broadcast("New server notification: A new resource was added!"); // ... send the HTTP response ... }
Key Notes
- Thread Safety: All access to the session list and message queues uses mutexes, which is critical if your server runs multiple
io_contextthreads (asadvanced_server.cppdoes). - Session Lifetime: Using
shared_ptrensures sessions aren’t destroyed while still referenced in the broadcast list. - Error Handling: If a session fails to write (e.g., the client disconnected), the
on_writeerror handler will close the session, and its destructor will automatically remove it from the server’s list.
That should give you a reliable way to broadcast messages to all connected WebSocket clients in your mixed server!
内容的提问来源于stack exchange,提问作者Fake Name

