boost asio async_read:读取的消息添加到自身中 [英] boost asio async_read: the read message adds to itself

查看:127
本文介绍了boost asio async_read:读取的消息添加到自身中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将PC用作服务器.客户端发送如下消息:"PART1:Part2",服务器执行必要的操作.我将boost的asio用于服务器代码.

I use my PC as a server. The client sends messages like: "PART1:Part2", and the server performs the necessary actions. I use boost's asio for the server code.

    void start_read()
    {
        boost::asio::async_read(socket_, input_buffer_,
            boost::asio::transfer_at_least(1),
            boost::bind(&tcp_connection::handle_read, shared_from_this(),
            boost::asio::placeholders::error));
    }

    // When stream is received handle the message from the client
    void handle_read(const boost::system::error_code& error)
    {
        if (!error)
        {
            boost::asio::streambuf::const_buffers_type bufs = input_buffer_.data();
            std::string msgstr(boost::asio::buffers_begin(bufs),
                               boost::asio::buffers_begin(bufs) +
                               input_buffer_.size());

            std::vector<std::string> msgVector;
            boost::split(msgVector, msgstr, boost::is_any_of(":"));

            messageFromClient_ = msgVector[0];
            valueFromClient_ = msgVector[1];
};

每秒向服务器发送一条消息,生成的msgstr如下所示:

Messages to the server are sent every second and the resulting msgstr looks like this:

PART1:part2a
PART1:part2bPART1:part2b
PART1:part2cPART1:part2cPART1:part2c
PART1:part2dPART1:part2dPART1:part2dPART1:part2d

这不是我想要的.我不想包含来自先前缓冲区的数据,即我想要这样做:

This is not what I want. I do not want to include data from the previous buffer, i.e. I want this:

PART1:part2a
PART1:part2b
PART1:part2c
PART1:part2d

我知道问题很可能出在这里:

I understand that the problem most likely lies here:

            std::string msgstr(boost::asio::buffers_begin(bufs),
                               boost::asio::buffers_begin(bufs) +
                               input_buffer_.size());

但是,我找不到适合我的情况的正确代码.

However, I cannot find the correct code that would work in my case.

试图这样做:

std::istream response_istream(&input_buffer_);
std::string msgstr;
response_istream >> msgstr;

前三遍,我得到了我所需要的,但随后的消息成倍增加.总是这样:

The first three times, I get what I need, but then the message is multiplied. It is always like this:

PART1:part2a
PART1:part2b
PART1:part2c
PART1:part2dPART1:part2d
PART1:part2ePART1:part2e
PART1:part2fPART1:part2fPART1:part2fPART1:part2f
PART1:part2gPART1:part2g

非常感谢.

推荐答案

The streambuf::data() member-function returns buffers representing the input sequence. To avoid accessing the data again, one can use the streambuf::consume() member-function to remove characters from the beginning of the input sequence. In this case, once data has been copied from input_buffer_ to msgstr, the input sequence can be cleared with:

input_buffer_.consume(input_buffer_.size());


这是一个完整的最小示例演示 consume()的行为:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>

// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

int main()
{
  using boost::asio::ip::tcp;
  boost::asio::io_service io_service;

  // Create all I/O objects.
  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
  tcp::socket server_socket(io_service);
  tcp::socket client_socket(io_service);

  // Connect client and server sockets.
  acceptor.async_accept(server_socket, boost::bind(&noop));
  client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
  io_service.run();

  // No-consuming case.
  { 
    std::cout << "Non-consuming example" << std::endl;
    boost::asio::streambuf streambuf;
    for (int i = 0; i < 5; ++i)
    {
      std::string data = "test";
      data += boost::lexical_cast<std::string>(i);

      // Write to server.
      std::size_t bytes_transferred =
          write(client_socket, boost::asio::buffer(data));

      // Read from client.
      read(server_socket, streambuf, 
           boost::asio::transfer_exactly(bytes_transferred));

      // Print results.
      std::string read_data(
        boost::asio::buffers_begin(streambuf.data()),
        boost::asio::buffers_end(streambuf.data()));
      std::cout << "size: " << streambuf.size() << ", "
                << "read: " << read_data << std::endl;
    }
  }

  // Consuming case.
  { 
    std::cout << "Consuming example" << std::endl;
    boost::asio::streambuf streambuf;
    for (int i = 0; i < 5; ++i)
    {
      std::string data = "test";
      data += boost::lexical_cast<std::string>(i);

      // Write to server.
      std::size_t bytes_transferred =
          write(client_socket, boost::asio::buffer(data));

      // Read from client.
      read(server_socket, streambuf, 
           boost::asio::transfer_exactly(bytes_transferred));

      // Print results.
      std::string read_data(
        boost::asio::buffers_begin(streambuf.data()),
        boost::asio::buffers_end(streambuf.data()));
      std::cout << "size: " << streambuf.size() << ", "
                << "read: " << read_data << std::endl;

      streambuf.consume(bytes_transferred);
    }
  }
}

输出:

Non-consuming example
size: 5, read: test0
size: 10, read: test0test1
size: 15, read: test0test1test2
size: 20, read: test0test1test2test3
size: 25, read: test0test1test2test3test4
Consuming example
size: 5, read: test0
size: 5, read: test1
size: 5, read: test2
size: 5, read: test3
size: 5, read: test4

请注意在使用情况下如何丢弃先前的数据.

Notice how in the consuming case, the previous data is discarded.

这篇关于boost asio async_read:读取的消息添加到自身中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆