boost::asio客户端连接停止接收数据 我真的很愿意学习Boo::ASIO,用于我的C++应用程序。 所以我从一个“简单”的客户端应用程序开始,它在我的笔记本电脑上编译和运行SN。这个想法很简单。客户端启动与服务器的连接,并每2秒询问一次答案。我有可能触发服务器的状态(比如说报警信号)。作为一种反应,当客户机尝试连接到服务器时,服务器将通知它我必须准备好接收一些数据(一个带有双精度和整数值的列表)。客户端请求列表,服务器通过连接发送通缉列表
问题:列表未完全传输。列表中的一大块将被发送并被正确接收,但之后我再也不会收到任何数据 由于我将应用程序拆分为多个类,因此代码如下: 客户:h 但是,只要我开始请求列表,我就会收到以下信息: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
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();
}
}