asio 套接字,在分隔符处拆分传入数据?

asio socket, split incoming data at a delimitator?

我正在用 C++ 从 asio 套接字读取数据。

我需要将传入数据解析为 json。为此,我需要获得一个 json 字符串条目。我正在添加一个字符';'在 json 字符串的末尾,现在我需要在读取时在该字符处拆分。我正在尝试这个:

int main()
{
    asio::io_service service;
    asio::ip::tcp::endpoint endpoint(asio::ip::address::from_string("127.0.0.1"), 4444);
    asio::ip::tcp::socket socket(service);
    std::cout << "[Client] Connecting to server..." << std::endl;
    socket.connect(endpoint);
    std::cout << "[Client] Connection successful" << std::endl;


    while (true)
    {

        std::string str;
        str.resize(2048);
        asio::read(socket, asio::buffer(str));

        std::string parsed;
        std::stringstream input_stringstream(str);


        if (std::getline(input_stringstream, parsed, ';'))
        {
                            
            std::cout << parsed << std::endl;
            std::cout<<std::endl;
        }

    

    }
}

但它给了我字符串的随机部分。

完整消息是:(用于测试,未 json 格式化)

this is the message in full, no more no less ;

我得到:

 full, no more no less

this is the message in full, no more no less

ull, no more no less

is is the message in full, no more no less

l, no more no less

 is the message in full, no more no less

 no more no less

我哪里错了?

谢谢!

我会使用 read_until:

#include <boost/asio.hpp>
#include <iostream>
#include <iomanip>
namespace asio = boost::asio;
using asio::ip::tcp;

int main()
{
    asio::io_service service;
    tcp::socket      socket(service);
    socket.connect({{}, 4444});

    std::string str;
    while (auto n = asio::read_until(socket, asio::dynamic_buffer(str), ';')) {
        std::cout << std::quoted(std::string_view(str).substr(0, n - 1)) << std::endl;
        str.erase(0, n);
    }
}

例如示例服务器:

paste -sd\; /etc/dictionaries-common/words  | netcat -l -p 4444

输出为:

"A"
"A's"
"AMD"
"AMD's"
"AOL"
"AOL's"
"Aachen"
"Aachen's"
"Aaliyah"
"Aaliyah's"
"Aaron"
"Aaron's"
"Abbas"
"Abbas's"
"Aberdeen's"
...
"zucchinis"
"zwieback"
"zwieback's"
"zygote"
"zygote's"
"zygotes"
"Ångström"
"Ångström's"
"éclair"
"éclair's"
"éclairs"
"éclat"
"éclat's"
"élan"
"élan's"
"émigré"
"émigré's"
"émigrés"
"épée"
"épée's"
"épées"
"étude"
"étude's"

其他提示

您可以使用任何动态缓冲区。这是 streambuf:

for (asio::streambuf buf; auto n = asio::read_until(socket, buf, ';');) {
    std::cout << std::string_view(
                     asio::buffer_cast<char const*>(buf.data()), n)
              << std::endl;
    buf.consume(n);
}

或者,混合,显示 dynamic_string_buffer 模拟与 streambuf 相同的概念:

std::string str;
for (auto buf = asio::dynamic_buffer(str);
     auto n   = asio::read_until(socket, buf, ';');) {
    std::cout << std::string_view(
                     asio::buffer_cast<char const*>(buf.data()), n)
              << std::endl;
    buf.consume(n);
}

或者:

std::vector<unsigned char> vec;
for (auto buf = asio::dynamic_buffer(vec);
     auto n   = asio::read_until(socket, buf, ';');) {
    std::cout << std::string_view(
                     asio::buffer_cast<char const*>(buf.data()), n)
              << std::endl;
    buf.consume(n);
}