Boost Beast 将带有字节数组的 json 发送到客户端抛出 websocket

Posted

技术标签:

【中文标题】Boost Beast 将带有字节数组的 json 发送到客户端抛出 websocket【英文标题】:Boost beast send json with byte array to client throw websocket 【发布时间】:2021-02-19 14:37:44 【问题描述】:

我有一个从字节数组转换为字符串的文件

processResultJson.append(reinterpret_cast<const char *const>(im->bits), sizeof(im->bits));
processResultJson.append(reinterpret_cast<const char *const>(im->bits), im_res->bmi->bmiHeader.biSizeImage);

docData.put("Image1", processResultJson);
boost::property_tree::json_parser::write_json(m_stream, SRegulaDR::docData);
resultString = m_stream.str();

size_t n = net::buffer_copy(buffer_.prepare(resultString.size()), net::buffer(resultString));        buffer_.commit(n);

在这种情况下,我得到 error_code=2 - End of file 然后error_code=995 I/O操作...

我如何发送带有转换为字符串的字节数组的 JSON 谢谢!!!

【问题讨论】:

什么情况下你会得到文件结尾?看不到阅读代码 【参考方案1】:

不要像使用 JSON 库一样使用属性树。它有众所周知的局限性:https://www.boost.org/doc/libs/1_75_0/doc/html/property_tree/parsers.html#property_tree.parsers.json_parser

特别注意数组的限制。

接下来,你没有写一个数组开始,而是写一个字符串。但由于它是二进制数据,它可能是一个有效的 JSON 字符串,这可能是错误的来源。

另外,您可能不需要再次复制整个 JSON 以将其放入缓冲区。相反,boost::asio::buffer(resultString) 将起作用(只要您确保 resultString 的生命周期足够,就像 buffer_ 一样)。

稍微测试一下就表明write_json 可以正确转义字符:

Live On Compiler Explorer

#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using namespace std::string_literals;

struct Im  std::array<std::uint64_t, 10> bits; ;

int main()

    auto im = std::make_unique<Im>(
            Im  0b0010'1100'1010'0010'0111'1100'0010 );

    std::string_view bitmsg(
        reinterpret_cast<char const*>(&im->bits),
        sizeof(im->bits));

    auto processResultJson = "some binary data: \0 \x10 \xef αβγδ\n"s;
    processResultJson += bitmsg;

    boost::property_tree::ptree docData; 
    docData.put("Image1", processResultJson);
    std::ostringstream oss;
    boost::property_tree::json_parser::write_json(oss, docData);

    std::cout << oss.str();

打印

"Image1": "some binary data: \u0000 \u0010 αβγδ\nu0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"

Json lint 将其报告为有效的 JSON(物有所值)

但是,请考虑通过以下方式加倍确定

使用 base64 编码对二进制数据进行编码 使用 Boost JSON 或其他合适的 JSON 库

使用 Boost JSON 演示

1.75.0 引入了适当的 JSON 库。让我们庆祝一下吧。

直接翻译为:https://godbolt.org/z/es9jGc

json::object docData;
docData["Image1"] = processResultJson;

std::string resultString = json::serialize(docData);

不过,您现在可以轻松地使用强类型的正确数组:https://godbolt.org/z/K9c6bc

json::object docData;
docData["Image1"] = json::array(im->bits.begin(), im->bits.end());

打印

"Image1":[46802882,0,0,0,0,0,0,0,0,0]

实际上,您也可以使用value_from: 的默认转换:

Live On Compiler Explorer

#include <iostream>
#include <boost/json/src.hpp> // for header-only
namespace json = boost::json;

struct Im  std::array<std::uint64_t, 10> bits; ;

int main()

    auto im = std::make_unique<Im>(
            Im  0b0010'1100'1010'0010'0111'1100'0010, /*...*/ );

    std::cout << json::object "Image1", json::value_from(im->bits)  ;

打印

"Image1":[46802882,0,0,0,0,0,0,0,0,0]

【讨论】:

我尝试使用 boost json,现在又遇到了另一个问题。如果我包含 我会收到 LNK2005 错误 我只添加 #include #include 并且只实现静态类成员作为 boost::json::object 并得到 LNK2005 错误 您可以链接它或包含源标题(就像我在计算机资源管理器中所做的那样) 您好。我把我的问题放在这个链接上更详细的代码你能帮忙吗! ***.com/questions/66298798/…

以上是关于Boost Beast 将带有字节数组的 json 发送到客户端抛出 websocket的主要内容,如果未能解决你的问题,请参考以下文章

C++ 使用 Boost.asio 和 Beast 库在正文中发送数据

使用 Boost Beast 处理并发请求

试图用 Boost::Beast 替换我的 libwebsocket 代码

如何使用 boost beast websocket 客户端收听 websocket 提要?

如何将带有字节数组的 json 发送到 web api / postman

Boost Beast websocket 服务器异步接受失败,缓冲区溢出