boost::asio::async_read 无限循环,接收数据为零字节
Posted
技术标签:
【中文标题】boost::asio::async_read 无限循环,接收数据为零字节【英文标题】:boost::asio::async_read loops infinite with zero byte of received data 【发布时间】:2017-07-27 18:55:06 【问题描述】:我正在尝试编写基于 IO_Service 的异步 TCP 客户端,其中 Async_write 工作正常,但 async_read 在无限循环中运行。在我尝试纠正这个问题的过程中,我发现在所有其他情况下 async_read 只是停止接收数据,在我停止服务器之前它什么也没有收到。以下是我在发布查询之前尝试过的代码和链接。
我尝试过的建议是exactly as mine、2、3and,但在所有情况下,我的 async_read 处理程序都没有读取任何内容。在一种也是唯一一种情况下,当我将缓冲区设置为 boost::asio::mutable_buffer bytes;
时,它会启动无限循环,而在其他情况下,我尝试了 boost::array<char, 512> bytes;
、boost::asio::streambuf bytes;
和 char bytes[512];
,其中未引发 async_read 处理程序。
在经历了所有这些解决方案之后,我现在很困惑:会不会是缓冲区的问题?在传递给阅读之前我需要初始化它吗 ?
请指导。
ScalableSocket::ScalableSocket()
//ctor
using namespace boost::asio;
service = boost::make_shared<io_service>();
work = boost::make_shared<io_service::work>(*service );
strand = boost::make_shared<io_service::strand>( *service );
worker_threads = boost::make_shared<boost::thread_group>();
worker_threads->create_thread(boost::bind(&ScalableSocket::WorkerThread,this));
resolver = boost::make_shared<boost::asio::ip::tcp::resolver> (*service);
tcp_socket= boost::make_shared<boost::asio::ip::tcp::socket> (*service);
boost::asio::ip::tcp::resolver::query q(boost::asio::ip::tcp::v4(),"192.168.100.96","9602");
boost::asio::ip::tcp::resolver::iterator it = resolver->resolve(q);
boost::asio::async_connect(*tcp_socket,it,boost::bind(&ScalableSocket::connect_handler,this,boost::asio::placeholders::error));
tcp_socket->set_option(boost::asio::ip::tcp::no_delay(true) );
ScalableSocket::~ScalableSocket()
//dtor
void ScalableSocket::PublishPost()
strand->post(boost::bind(&ScalableSocket::OnSend,this));
void ScalableSocket::OnSend()
boost::array<char, 6> a = 'a', 'b', 'c', 'd', 'e' ;
boost::asio::async_write(*tcp_socket,boost::asio::buffer(a),
boost::bind(&ScalableSocket::write_handler, this, boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
void ScalableSocket::WorkerThread()
while( true )
try
boost::system::error_code ec;
service->run( ec );
if( ec )
///LOGE(ec);
break;
catch( std::exception & ex )
///LOGE(ex.what());
void ScalableSocket::connect_handler(const boost::system::error_code &ec)
if (!ec)
PublishPost();
/* boost::asio::async_read(*tcp_socket,
boost::asio::buffer(bytes),
boost::bind(&ScalableSocket::read_handler, this,
boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
*/
///https://***.com/questions/4527443/problems-using-boostasioasync-read
boost::shared_ptr<boost::array<char, 512>> buf(new boost::array<char, 512>);
boost::asio::async_read(*tcp_socket,boost::asio::buffer(*buf),
boost::bind(&ScalableSocket::read_handler, this,buf,
boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
else
cout<<" Some error connecting to Exchange "<< ec.message()<<endl;
void ScalableSocket::OnTimer(const boost::system::error_code &ec)
if(!ec)
printf("\n\n Heartbeat event raised sending KeepAlive to exchange \n\n");
PublishPost();
HeartBeatTimer->async_wait(boost::bind(&ScalableSocket::OnTimer,this, boost::asio::placeholders::error));
void ScalableSocket::recvData()
boost::system::error_code error;
boost::array<char, 1024> buf;
//for(;;)
size_t len = tcp_socket->read_some(boost::asio::buffer(buf), error);
cout<<"\n Recv data size is "<<len;
void ScalableSocket::read_handler(boost::shared_ptr<boost::array<char, 512>> buf,const boost::system::error_code &ec,std::size_t bytes_transferred)
if (!ec )//&& bytes_transferred > 0)
///recvData(); /// If i enable this code during infinite loop it start getting data that means socket has no issue
cout << " Data size recieved "<< bytes_transferred<<endl;
boost::asio::async_read(*tcp_socket,boost::asio::buffer(*buf),
boost::bind(&ScalableSocket::read_handler, this,buf,
boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
else
/// Some issue with socket publish error , inform user and reconnect
cout<<" Some error reading data from Exchange "<< ec.message()<<endl;
void ScalableSocket::write_handler(const boost::system::error_code& error,std::size_t bytes_transferred)
if(!error)
/// data Sent successfully
cout<< " Data sent size "<< bytes_transferred<<endl;
else
cout<<" Some error sending data to Exchange "<< error.message()<<endl;
【问题讨论】:
但是你知道asnyc_read
不会“返回”/调用处理程序,直到给定的缓冲区完全填满,对吧?
我使用了这种 512 类型的缓冲区,一旦我使用 boost 流缓冲区或可变缓冲区未能接收到任何东西,然后我尝试在堆栈本身的一些解决方案之后使用该 512 的东西
一些标点符号有助于识别您的评论。尝试发送 512 字节及以上的数据,看看是否正确接收。
感谢@Blacktempel 救了我。你是 100% 正确的。都是我的错。将 asio::async_read 替换为 socket.async_read_some 并且它起作用了。
【参考方案1】:
asnyc_read
不会“返回”/调用处理程序,直到给定的缓冲区完全填满。
asnyc_read_some
将在读取一些字节后返回。这可能是您正在寻找的功能。
记得使用asnyc_read_some
正确处理接收到的数据。如果您发送 512 个字节,它可能会在几次读取中到达,具体取决于机器。
【讨论】:
以上是关于boost::asio::async_read 无限循环,接收数据为零字节的主要内容,如果未能解决你的问题,请参考以下文章
boost::asio::async_read 不回调我的处理函数
boost::asio::async_read 无限循环,接收数据为零字节