【问题标题】:asio socket, split incoming data at a delimitator?asio套接字,在分隔符处拆分传入数据?
【发布时间】:2022-02-24 23:52:27
【问题描述】:

我正在从 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

我哪里错了?

谢谢!

【问题讨论】:

  • 嗨,这似乎建议使用 getline,就像我上面的代码一样。
  • 查看答案。他们使用async_read_until。问题不是答案。
  • 道歉。我试图了解如何使用这个函数,但我能找到的最简单的例子是:`std::vector buffer; asio::async_read_until(socket, asio::dynamic_buffer(buffer, 16), ';', [&](asio::error_code error, std::size_t bytes_transferred); { std::cout
  • The first answer 展示了如何使用分隔符。

标签: c++ sockets boost-asio


【解决方案1】:

我会使用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_bufferstreambuf 建模相同的概念:

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

【讨论】:

  • 嗨,谢谢。我在我的字符串上运行此代码,它不打印任何内容。我的连接有效,并且字符串具有; 字符。可能出了什么问题?
  • 啊!删除空格有这个工作。有没有办法通过这种方法使用包含空格的字符串?再次感谢!
  • 它已经适用于他们:i.imgur.com/aA80PPw.gif 我很确定你仍在使用istream (en.cppreference.com/w/cpp/string/basic_string/…)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 2013-11-27
  • 1970-01-01
  • 2019-11-19
相关资源
最近更新 更多