【问题标题】:Lambda for async_read_until does not initialize length parameterasync_read_until 的 Lambda 未初始化长度参数
【发布时间】:2014-12-04 23:13:50
【问题描述】:

我正在尝试使用带有 boost::asio::async_read_until 的 c++11 lambda,如下所示:

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

我观察到的是长度=0。 ec 被适当地设置为 boost EOF 代码。

当我将成员(即 buffer_)转换为字符串时,我也会看到数据。

任何有关初始化长度的建议都会有所帮助。

示例输出:

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

【问题讨论】:

  • /你如何/如何观察你所说的话。可能是调试器让您/自己感到困惑
  • “未填充”是什么意思?您从 printf 语句中看到了什么输出?此外,您似乎根本没有打印ec。你能把它也包括在你的输出中吗?

标签: c++ c++11 boost lambda boost-asio


【解决方案1】:

试试

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

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

或者更好,

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

%d 不是 size_t 的正确格式。 (这就是 C++ 被发明的原因。几十年前)

注意:如果您启用警告 (-Wall -Wextra -pedantic),您的编译器会告诉您大部分内容

现在,docs say

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

所以,由于 ec 是 EOF,这说明 length 也是 0。

以下示例打印:Live On Coliru

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

(假设响应服务器发送“hello world\n”);

完整示例:

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

【讨论】:

  • 感谢您的回复,但我不认为这是问题所在。我实际上正在使用 boost::log。为了清楚起见,我只是用 printf 替换了它。并且不会将 size_t 自动类型转换为 %d 吗?
  • 我不在乎你相信什么。测试一下。我刚刚添加了一个更严重的错误,缺少c_str()。请:编译时启用警告,如果可以的话,请使用 C++ :)
  • 那是什么?也许您可以将其编辑到问题中?注意:由于您使用原始临时 ss.str() 作为 printf("%s", ...) 的参数,因此您的程序展示了 Undefined Behaviour 这可以解释为什么从未使用过 if (!ec)
  • 好的,我已经更新了问题。感谢您的建议。 stringstream 似乎确实可以正确打印。但请注意,这是来自类的成员变量。好的,所以我修改了打印语句如下:'log()->debug("received %lu bytes && ec: %d", length, ec);'并观察到 ​​ec 是一个提升 EOF。这很好,但是为什么长度仍然没有填写?
  • @bge0 查看我的更新答案。 [我希望您确实还修复了将ss.str() 的日志记录到ss.str().c_str()。别忘了。] 哦,这里是独立的复制器 Live On Coliru
猜你喜欢
  • 2012-04-24
  • 1970-01-01
  • 2016-05-03
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 2019-01-25
  • 2012-06-06
  • 2012-06-05
相关资源
最近更新 更多