0

I write a websocket though boost, and I receive the message though the client in chrome. When I use ws, it works well, I can receive correct msg. but when I use wss, it works bad, and said could not decode a text frame as UTF 8.

the picture is what's wrong is ssl mode. wrong msg in ssl mode

c++ send msg code

  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 code

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

Where does this odd character come from? What is the problem? How to fix this ?

4

1 回答 1

2

The problem is with sending data. async_write() ends immediately, it doesn't make a copy of data buffer, you have to ensure that data passed into boost::asio::buffer lives until the full message will be sent.

Even if we added some delay code between async_write and ending brace {:

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

this code will not work also, because toStyledString returns string by value. So temporary string is created, string::data() is called, async_write() ends, and you have dangling pointer inside task initiated by async_write().

Quick solution, prolong lifetime of string for example by using smart pointer:

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

pass buf by boost::asio::buffer(*buf), and capture it by value inside lambda: [&,sp,buf].

于 2019-06-26T13:53:23.410 回答