如何解决无法通过Boost WebSocket将文本框架解码为UTF 8

时间:2019-06-26 12:14:43

标签: javascript google-chrome boost beast-websockets

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

图片有问题的是ssl模式。 wrong msg in ssl mode

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)};

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

1 个答案:

答案 0 :(得分: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();
                 }));

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