【问题标题】:How to resolve could not decode a text frame as UTF 8 though boost websocket如何解决无法通过 boost websocket 将文本帧解码为 UTF 8
【发布时间】:2019-06-26 12:14:43
【问题描述】:

我通过 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)};

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

【问题讨论】:

  • 我不明白它是如何工作的。首先toStyledString 按值返回字符串,所以data() 你有悬空指针。其次,async_write 立即返回,因此可以在发送消息之前销毁 jsonMsg。

标签: javascript google-chrome boost beast-websockets


【解决方案1】:

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

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

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

此代码也不起作用,因为toStyledString 返回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 中的值捕获它:[&amp;,sp,buf]。

【讨论】:

  • 兄弟,谢谢你,这解决了我的问题,但我还没有弄清楚。如果这是错误的,为什么它在所有计算机上的 WS 中都能正常工作,而在 WSS 中,它在我们大多数同学的设备上都能正常工作,除了一台。
  • 很难说它为什么有效。您原始代码中的问题引入了未定义的行为。有了 UB,一切都可能发生,甚至代码看起来都可以正常工作,但这只是幸运的突破。
  • 因为 WS 比 WSS 快得多,所以 I/O 在临时超出范围之前完成。
猜你喜欢
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 2015-07-19
  • 2023-03-10
相关资源
最近更新 更多