【问题标题】:How to 'read' from a (binary==true) boost::beast::websocket::stream<tcp::socket> into a buffer (boost::beast::flat_buffer?) so it is not escaped?如何从 (binary==true) boost::beast::websocket::stream<tcp::socket> '读取'到缓冲区 (boost::beast::flat_buffer?) 所以它不会被转义?
【发布时间】:2020-03-31 18:11:54
【问题描述】:

我正在使用 boost::beast 将数据从 websocket 读取到 std::string。我密切关注boost 1.71.0 中的示例websocket_sync_client.cpp,有一个变化——I/O 以二进制形式发送,服务器端没有文本处理程序,只有二进制流。因此,在示例中,我添加了一行代码:

    // Make the stream binary?? https://github.com/boostorg/beast/issues/1045
    ws.binary(true);

一切都按预期工作,我“发送”一条消息,然后使用 boost::beast::buffers_to_string 将我发送的消息的响应“读取”到 std::string:

        // =============================================================
        // This buffer will hold the incoming message
        beast::flat_buffer wbuffer;

        // Read a message into our buffer
        ws.read(wbuffer);
        // =============================================================

        // ==flat_buffer to std::string=================================
        string rcvdS = beast::buffers_to_string(wbuffer.data());
        std::cout << "<string_rcvdS>" << rcvdS << "</string_rcvdS>" << std::endl;
        // ==flat_buffer to std::string=================================

这和我预期的差不多,除了在(二进制)流的数据上发生了某种转义。 毫无疑问,某些增强逻辑层(可能是字符特征?)已启用/导致所有不可打印字符为 '\u????'转义的、人类可读的文本。

读取的二进制数据包含许多(有意的)不可打印的 ASCII 控制字符来分隔/组织消息中的数据块:

我宁愿不让流转义这些不可打印的字符,因为无论如何我都必须“撤消”这项工作,如果我不能强制“读取”缓冲区按原样保留数据,那么原始数据。如果我必须找到另一个 boost API 来撤消转义,那只是浪费处理,这无疑会损害性能。

我的问题必须有一个简单的解决方案。 如何使生成的 flat_buffer(即 ws.read 到 'rcvdS' /class,这样就不会发生转义?

这是一个视觉帮助 - 显示预期数据与实际数据:

【问题讨论】:

    标签: c++ boost websocket


    【解决方案1】:

    Beast 不会以任何方式更改消息的内容。 binary() 和 text() 唯一要做的就是在另一端收到的消息中设置一个标志。文本消息根据合法字符集进行验证,而二进制消息则不是。 Beast 永远不会更改消息数据。 buffers_to_string 只是将缓冲区中的字节传输到 std::string,它不会转义任何内容。因此,如果缓冲区包含空值,或者说是 ctrl+A,您将分别在 std::string 中获得 0x00 和 0x01。

    如果您的信息正在被编码或翻译,并不是 Beast 在做这件事。也许这是将原始字节写入 std::cout 的结果?或者它可能是您用来在您发布的图像中显示这些消息的任何内容。我注意到您提供的代码与图片不符。

    【讨论】:

    • 我发布的图片是 Notepad++ 如何将 ASCII 不可打印字符呈现为黑色“ASCII 码”。即,如果数据包含换页 ACII 字符(1 个字节),则记事本显示黑色“FF”图标。这是我可以直观地显示数据中不可打印的 ASCII 的最佳方式。当我进入“ws.read(wbuffer);”命中的所有代码时使用 Visual Studio,我在 beast\websocket\impl\read.hpp 中逐步执行“read_some”,最终逐步通过“impl.rd_utf8.write”和“impl.rd_utf8.finish()”,我相信它就在那里导致它......但我仍在挖掘。 :-|
    • rd_utf8 只是一个 UTF-8 验证器,它不会修改任何内容。这就是文本和二进制之间的区别:文本消息被检查为有效的 utf-8,而二进制消息则不是。否则它们是相同的。野兽不会改变消息内容!
    • 您是如何将这些数据导入 Notepad++ 的?
    • 抱歉耽搁了,我正在使用 Boost.Beast 进行 C++ 概念验证,它将替换本机 C++ 控制台应用程序中的网络通信类。因此,目前,它正在从后端服务器的 Java Websocket 连接接收所有二进制通信。我捕获了从服务器到达当前客户端的前 6 条响应消息。我首先通过创建一个文件并将二进制数据写入文件来捕获它们。我还在调试客户端时使用 Visual Studio 捕获了它们。我将通过电子邮件将包含前 6 条(二进制)消息的 TXT 文件发送给您。
    • @"Vinnie Falco" 将数据导入 Notepad++,这样您就可以“看到”不可打印的字符,我下载了 Unifont,并将 Notepad++ 更改为使用 Unifont。我喜欢的是这种字体将不可打印的 ASCII 字符的外观更改为代表它们的 ASCII 名称,并且它们以相反的方式出现。这使得“查看”数据中每个不可打印的 ASCII 字符的确切内容变得非常容易。
    【解决方案2】:

    如果有其他人登陆这里,请放心,这是您的服务器端,而不是客户端正在转义您的数据。

    【讨论】:

      猜你喜欢
      • 2018-02-18
      • 2018-10-06
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-27
      相关资源
      最近更新 更多