如何解决无法通过提升 websocket 将文本框架解码为 UTF 8

How to resolve could not decode a text frame as UTF 8 though boost websocket

我通过 boost 编写了一个 websocket,并且我通过 chrome 中的客户端接收了消息。 当我使用 ws 时,它运行良好,我可以收到正确的消息。 但是当我使用 wss 时,它工作不好,并说无法将文本框架解码为 UTF 8。

图片是ssl模式出了问题。

c++ 发送消息代码

  Json::Value jsonMsg;
        jsonMsg["msgType"] = Json::Value("MspServiceStartUp");
        jsonMsg["version"] = Json::Value(std::string(MSP_VERSION));
        ws_->async_write(boost::asio::buffer((void *) jsonMsg.toStyledString().data(), jsonMsg.toStyledString().size()),
                         boost::asio::bind_executor(*strand_, [&, sp](boost::system::error_code ec1,
                                                                      std::size_t bytes_transferred1) {
                             boost::ignore_unused(bytes_transferred1);
                             if (ec1) {
                                 LOG_ERR << "async write failed, ec = " << ec1 << ", msg = "
                                         << ec1.message();
                                 return;
                             }
                             // Clear the buffer
                             buffer_->consume(buffer_->size());
                             task();
                         }));
    }

js代码

var ws=new WebSocket("wss://localhost.com:17801/");
ws.onopen=()=>{console.log('ws open')};
ws.onclose=()=>{console.log('ws close')};
ws.onmessage=(msg)=>{console.log('ws onMessage');console.log(msg)};

这个奇怪的字符是从哪里来的? 问题是什么?如何解决这个问题?

问题在于发送数据。 async_write() 立即结束,它不会复制数据缓冲区,您必须确保传递到 boost::asio::buffer 的数据在发送完整消息之前一直有效。

即使我们在 async_write 和结束大括号 { 之间添加了一些延迟代码:

async_write(boost::asio::buffer((void *) jsonMsg.toStyledString().data(), ..));
... some code waiting until write is completed
}

此代码也不起作用,因为 toStyledString returns string 。 所以临时 string 被创建, string::data() 被调用, async_write() 结束,并且你在由 async_write().

发起的任务中有悬空指针

快速解决方案,例如通过使用智能指针延长字符串的生命周期:

std::shared_ptr<std::string> buf(std::make_shared<std::string>(jsonMsg.toStyledString()));
ws_->async_write(boost::asio::buffer(*buf),
                 boost::asio::bind_executor(*strand_, 
                 [&, sp, buf](boost::system::error_code ec1,
                             std::size_t bytes_transferred1) 
                 {
                         boost::ignore_unused(bytes_transferred1);
                         if (ec1) {
                             LOG_ERR << "async write failed, ec = " << ec1 << ", msg = "
                                     << ec1.message();
                             return;
                         }
                         // Clear the buffer
                         buffer_->consume(buffer_->size());
                         task();
                 }));

通过 boost::asio::buffer(*buf) 传递 buf,并通过 lambda 中的值捕获它:[&,sp,buf].