WebSocketSession.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "WebSocketSession.h"
  2. #include "WebSocketHandler.h"
  3. #include "Logger.h"
  4. #include <boost/beast/version.hpp>
  5. WebSocketSession::WebSocketSession(tcp::socket&& socket, http::request<http::dynamic_body> req)
  6. : ws_(std::move(socket)), req_(std::move(req)) {
  7. }
  8. WebSocketSession::~WebSocketSession() {
  9. close();
  10. // 注意:不应该在这里调用RemoveClient,因为如果WebSocketHandler仍然持有shared_ptr,
  11. // 析构函数永远不会被调用。正确的做法是在RemoveClient时触发析构。
  12. }
  13. void WebSocketSession::run() {
  14. // 设置建议的超时设置
  15. beast::get_lowest_layer(ws_).expires_never();
  16. // 设置WebSocket超时参数
  17. ws_.set_option(websocket::stream_base::timeout{
  18. std::chrono::seconds(30), // handshake timeout
  19. std::chrono::seconds(30), // idle timeout
  20. true // 取消关闭连接前的静默超时
  21. });
  22. // 设置装饰器来改变服务器握手
  23. ws_.set_option(websocket::stream_base::decorator(
  24. [](websocket::response_type& res) {
  25. res.set(http::field::server, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-server-async");
  26. }));
  27. // 接受WebSocket握手
  28. ws_.async_accept(
  29. req_,
  30. beast::bind_front_handler(&WebSocketSession::on_accept, shared_from_this()));
  31. }
  32. void WebSocketSession::on_accept(beast::error_code ec) {
  33. if (ec) {
  34. LOG_ERROR("WebSocket accept failed: " + ec.message());
  35. return;
  36. }
  37. LOG_INFO("WebSocket connection established");
  38. // 开始读取消息
  39. do_read();
  40. }
  41. void WebSocketSession::do_read() {
  42. if (closed_.load()) {
  43. return;
  44. }
  45. // 读取消息
  46. ws_.async_read(
  47. buffer_,
  48. beast::bind_front_handler(&WebSocketSession::on_read, shared_from_this()));
  49. }
  50. void WebSocketSession::on_read(beast::error_code ec, std::size_t bytes_transferred) {
  51. boost::ignore_unused(bytes_transferred);
  52. if (ec) {
  53. if (ec != websocket::error::closed) {
  54. LOG_ERROR("WebSocket read failed: " + ec.message());
  55. }
  56. // 通知处理器移除客户端
  57. if (websocket_handler_) {
  58. websocket_handler_->RemoveClient(shared_from_this());
  59. }
  60. return;
  61. }
  62. // 处理接收到的消息
  63. std::string message = beast::buffers_to_string(buffer_.data());
  64. buffer_.clear();
  65. // 调用消息处理回调
  66. if (message_handler_) {
  67. message_handler_(shared_from_this(), message);
  68. }
  69. // 继续读取下一个消息
  70. do_read();
  71. }
  72. void WebSocketSession::safe_send(std::shared_ptr<std::string> message) {
  73. if (closed_.load()) {
  74. return;
  75. }
  76. std::lock_guard<std::mutex> lock(send_mutex_);
  77. send_queue_.push(message);
  78. if (!is_sending_) {
  79. do_write();
  80. }
  81. }
  82. void WebSocketSession::do_write() {
  83. // 注意:此方法应该在持有send_mutex_锁的情况下调用
  84. if (closed_.load() || send_queue_.empty()) {
  85. is_sending_ = false;
  86. return;
  87. }
  88. is_sending_ = true;
  89. current_message_ = send_queue_.front();
  90. send_queue_.pop();
  91. // 使用成员变量current_message_确保在异步操作期间消息不会被销毁
  92. ws_.async_write(
  93. net::buffer(*current_message_),
  94. beast::bind_front_handler(&WebSocketSession::on_write, shared_from_this()));
  95. }
  96. void WebSocketSession::on_write(beast::error_code ec, std::size_t bytes_transferred) {
  97. boost::ignore_unused(bytes_transferred);
  98. std::lock_guard<std::mutex> lock(send_mutex_);
  99. current_message_.reset(); // 清理当前消息
  100. if (ec) {
  101. LOG_ERROR("WebSocket write failed: " + ec.message());
  102. is_sending_ = false;
  103. // 如果写入失败,关闭连接并通知处理器移除客户端
  104. if (websocket_handler_) {
  105. close();
  106. websocket_handler_->RemoveClient(shared_from_this());
  107. }
  108. return;
  109. }
  110. if (!send_queue_.empty()) {
  111. do_write();
  112. } else {
  113. is_sending_ = false;
  114. }
  115. }
  116. void WebSocketSession::close() {
  117. if (closed_.exchange(true)) {
  118. return; // 已经关闭
  119. }
  120. beast::error_code ec;
  121. ws_.close(websocket::close_code::normal, ec);
  122. if (ec) {
  123. LOG_ERROR("WebSocket close failed: " + ec.message());
  124. }
  125. }
  126. void WebSocketSession::set_message_handler(MessageHandler handler) {
  127. message_handler_ = handler;
  128. }