boost::asio客户端连接停止接收数据 我真的很愿意学习Boo::ASIO,用于我的C++应用程序。 所以我从一个“简单”的客户端应用程序开始,它在我的笔记本电脑上编译和运行SN。这个想法很简单。客户端启动与服务器的连接,并每2秒询问一次答案。我有可能触发服务器的状态(比如说报警信号)。作为一种反应,当客户机尝试连接到服务器时,服务器将通知它我必须准备好接收一些数据(一个带有双精度和整数值的列表)。客户端请求列表,服务器通过连接发送通缉列表

boost::asio客户端连接停止接收数据 我真的很愿意学习Boo::ASIO,用于我的C++应用程序。 所以我从一个“简单”的客户端应用程序开始,它在我的笔记本电脑上编译和运行SN。这个想法很简单。客户端启动与服务器的连接,并每2秒询问一次答案。我有可能触发服务器的状态(比如说报警信号)。作为一种反应,当客户机尝试连接到服务器时,服务器将通知它我必须准备好接收一些数据(一个带有双精度和整数值的列表)。客户端请求列表,服务器通过连接发送通缉列表,c++,boost,connection,client,boost-asio,C++,Boost,Connection,Client,Boost Asio,问题:列表未完全传输。列表中的一大块将被发送并被正确接收,但之后我再也不会收到任何数据 由于我将应用程序拆分为多个类,因此代码如下: 客户:h 但是,只要我开始请求列表,我就会收到以下信息: Request Nr: 6 Socket created Waiting answer from Server... HTTP/1.1 200 OK Server OK, start retrieving data List Data received. 0 1 3 22 1

问题:列表未完全传输。列表中的一大块将被发送并被正确接收,但之后我再也不会收到任何数据

由于我将应用程序拆分为多个类,因此代码如下:

客户:h

但是,只要我开始请求列表,我就会收到以下信息:

Request Nr: 6
Socket created
Waiting answer from Server...

HTTP/1.1   200   OK
Server OK, start retrieving data

List Data received.
0   1   3   22  1   1000    1   3   51.9896769729347099 8.62269043922424316 35  1   0
1   0   3   16  1   1000    3   1   51.9908133374338917 8.6260378360748291  0   1   0
2   0   3   16  1   5000    3   1   51.9903706872495235 8.62733602523803711 -30 1   1
3   0   3   16  1   1000    3   1   51.9906
IO Service status: 7
这并不是全部清单。 该列表还有几行:

0   1   3   22  1   1000    1   3   231.9896769729347099    83.62269043922424316    35  1   0
1   0   3   16  1   1000    3   1   221.9908133374338917    82.6260378360748291 0   1   0
2   0   3   16  1   5000    3   1   121.9903706872495235    84.62733602523803711    -30 1   1
3   0   3   16  1   1000    3   1   45.99066872495235564
82.62733602523803711-30 1 1 2 0 3 16 1 5000 3 1 124.9903706872495235 24.62733602324442711 -30 1 1 3 0 3 16 1 1000 3 1 22.99066872495235564 22.6223535335351-30 1 1

在我看来,这种联系(也许我错了)突然中断了。然后,它从一开始就重新开始,并接收剩余的行。 但是我需要马上收到全部名单。 怎么了


编辑:非常感谢rhashimoto。我帮助我了解了正在发生的事情以及可以改进的地方。 他的anwser没有解决这个问题。因为,如果我这样做:

void Client::run( void )
{
    if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now() - begin_time_ ) > server_response_delay_ ) 
    {
        begin_time_ = std::chrono::high_resolution_clock::now();

        boost::asio::ip::tcp::resolver::query local_query( host_server_, port_ );

        resolver_.async_resolve( local_query, boost::bind( &Client::handleResolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator ) );

        size_t service_status = io_service_.run();

        if( flag_ ) {

            list << &response_;

            std::cout << list.str();
        }

        std::cout << "IO Service status: " << service_status << std::endl << std::endl;

        io_service_.reset();

    }
}
void客户端::运行(void)
{
if(std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-begin_time)>服务器响应延迟)
{
开始时间=标准::时钟::高分辨率时钟::现在();
boost::asio::ip::tcp::resolver::query local\u query(主机、服务器、端口);
解析程序.异步解析(本地查询,boost::bind(&Client::handleResolve,this,boost::asio::placeholders::error,boost::asio::placeholders::iterator));
大小\服务\状态=io\服务\运行();
如果(标志){

列出您的
async\u read*
处理程序缺少
bytes\u transfered
参数。它们应该具有:

请注意,您还需要在绑定占位符的任何位置添加占位符参数

不过,这不是你的问题所在。问题在于你在阅读之前打印了回复正文。请注意,这一行:

/* HERE I READ A BLOCK OF THE LIST BUT NOT THE WHOLE LIST!!!! */
std::cout << &response_;
boost::asio::async_read( socket_, response_, boost::asio::transfer_at_least(1), 
                         boost::bind(&Client::readContent, this, boost::asio::placeholders::error ) );
好的,现在您可能想知道如何在阅读之前打印出正文中的任何部分。答案是您曾经阅读HTTP状态行和所有标题。文档注释:

在成功的异步读取操作之后,streambuf可能 包含分隔符之外的其他数据。应用程序将 通常将该数据保留在streambuf中以供后续处理 异步读取直到要检查的操作

因此,您正在打印出没有使用
std::istream
使用的附加数据。这恰好是列表的第一部分。然后您继续阅读其余部分,但您没有打印出来,因此它只是位于
流buf
中(您会在下一个请求中看到它)

读取完成后,尝试将该
std::cout
行移动到
Client::run()

void Client::run( void )
{
    if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now() - begin_time_ ) > server_response_delay_ ) 
    {
        begin_time_ = std::chrono::high_resolution_clock::now();

        boost::asio::ip::tcp::resolver::query local_query( host_server_, port_ );

        resolver_.async_resolve( local_query, boost::bind( &Client::handleResolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator ) );

        size_t service_status = io_service_.run();

        // ******************************
        // ***** MOVE PRINT TO HERE *****
        // ******************************
        std::cout << &response_;

        std::cout << "IO Service status: " << service_status << std::endl << std::endl;

        io_service_.reset();
    }
}
void客户端::运行(void)
{
if(std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-begin_time)>服务器响应延迟)
{
开始时间=标准::时钟::高分辨率时钟::现在();
boost::asio::ip::tcp::resolver::query local\u query(主机、服务器、端口);
解析程序.异步解析(本地查询,boost::bind(&Client::handleResolve,this,boost::asio::placeholders::error,boost::asio::placeholders::iterator));
大小\服务\状态=io\服务\运行();
// ******************************
//******将打印移到此处*****
// ******************************

std::您是按照rhashimoto的建议移动了
ostream
插入,还是现在调用它两次了?
ostream
的插入操作将消耗streambuf的输入序列()。此外,与
transfer\u至少(1)
链相比,使用完成条件可能更具选择性,表达意图也更简洁。感谢您的评论。我尝试了“transfer\u all”()'方法,效果非常好。我所做的是:我完全更改并重写了我的代码。我在上面发布的代码中发现了更多错误和误解。最后我明白了rhashimoto所说的:我的代码读取消息头+一些数据。然后它再次运行并获取剩余的数据。因为它现在被拆分了分为两条流,我无法一次获得所有信息。我没有按照他说的做,但我更了解它的工作原理
void handler(
  const boost::system::error_code& error, // Result of operation.
  std::size_t bytes_transferred           // Number of bytes copied into the
                                          // buffers. If an error occurred,
                                          // this will be the  number of
                                          // bytes successfully transferred
                                          // prior to the error.
);
/* HERE I READ A BLOCK OF THE LIST BUT NOT THE WHOLE LIST!!!! */
std::cout << &response_;
boost::asio::async_read( socket_, response_, boost::asio::transfer_at_least(1), 
                         boost::bind(&Client::readContent, this, boost::asio::placeholders::error ) );
void Client::run( void )
{
    if( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now() - begin_time_ ) > server_response_delay_ ) 
    {
        begin_time_ = std::chrono::high_resolution_clock::now();

        boost::asio::ip::tcp::resolver::query local_query( host_server_, port_ );

        resolver_.async_resolve( local_query, boost::bind( &Client::handleResolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator ) );

        size_t service_status = io_service_.run();

        // ******************************
        // ***** MOVE PRINT TO HERE *****
        // ******************************
        std::cout << &response_;

        std::cout << "IO Service status: " << service_status << std::endl << std::endl;

        io_service_.reset();
    }
}