简体   繁体   中英

Lambda for async_read_until does not initialize length parameter

I am trying to use a c++11 lambda with boost::asio::async_read_until as follows:

void TCPSession::readData()
{
  auto self(shared_from_this());
  boost::asio::async_read_until(socket_, buffer_, "\r\n",
  [this, self](const boost::system::error_code& ec, std::size_t length)
  {
    log()->debug("received %lu bytes && ec: %d", length, ec); //use boost::log for compile time checking
    std::ostringstream ss;
    ss << &buffer_;
    log()->debug("Received data: %s",ss.str());
    if (!ec){
      log()->debug("We never get here!");
      [... process data ...]
      readData();
    }
  }
 );
}

What I observe is that that length=0. The ec is set appropriately to the boost EOF code.

I also see the data when I convert the member (ie buffer_) to a string.

Any suggestions on getting the length initialized would be helpful.

An example output:

2014-10-09 14:47:56.968142 [tcp-session] debug: received 0 bytes && ec: asio.misc:2
2014-10-09 14:47:56.974593 [tcp-session] debug: Received data: test7.2.3.5 0.18722307655 2014-10-09 14:47:55.343591
test7.2.3.5 -0.0691607464759 2014-10-09 14:47:55.343837
test7.2.3.5 0.151471040421 2014-10-09 14:47:55.344017
test7.2.3.5 0.172789025585 2014-10-09 14:47:55.344211
test7.2.3.5 0.0409326066787 2014-10-09 14:47:55.344406

Try

printf("received %lu bytes", length);

// ...
printf("Received data: %s", ss.str().c_str());

Or better yet,

std::cout << "received " << length << " bytes\n";
// ...
std::cout << "Received data: " << ss.str();

%d is not the right format for size_t. (This is why C++ was invented. Some decades ago)

Note: Your compiler would have told you most of this if you enabled warnings ( -Wall -Wextra -pedantic )

Now, the docs say that

 // The number of bytes in the streambuf's get
 // area up to and including the delimiter.
 // 0 if an error occurred.

So, since the ec is EOF, this explains that length is also 0.

The below sample prints: Live On Coliru

received 0 bytes, ec: End of file
Received data: hello world
byebye

(Assuming that the responding server sends "hello world\\n");

Full Sample:

#include <boost/asio.hpp>   
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <cstring>
#include <iostream>

struct TCPSession : boost::enable_shared_from_this<TCPSession>
{
    void readData();

    TCPSession(boost::asio::io_service& svc) : socket_(svc) {
        using boost::asio::ip::tcp;
        socket_.connect(tcp::endpoint { {}, 6767 });
    }
    boost::asio::ip::tcp::socket socket_;
    boost::asio::streambuf buffer_;
};

void TCPSession::readData()
{
  auto self(shared_from_this());
  boost::asio::async_read_until(socket_, buffer_, "\r\n",
  [this, self](const boost::system::error_code& ec, std::size_t length)
  {
    std::cout << "received " << length << " bytes, ec: " << ec.message() << "\n";

    std::ostringstream ss;
    ss << &buffer_;
    std::cout << "Received data: " << ss.str();

    if (!ec){
      std::cout << "We never get here!";
      //[... process data ...]
      readData();
    }

    std::cout << "byebye\n";
  }
 );
}

int main()
{
    boost::asio::io_service svc;
    auto sess = boost::make_shared<TCPSession>(svc);

    sess->readData();
    svc.run();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM