有一个很难理解与升压ASIO TCP一些概念与async_read和async_write [英] Having a hard time understanding a few concepts with Boost ASIO TCP with async_read and async_write
问题描述
我有一个很难理解的正确方法使用async_read和async_write时,我应该构建一个TCP客户端。在<一个href=\"http://www.boost.org/doc/libs/1_38_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp\"相对=nofollow>例子似乎做一个async_read连接后,然后在处理程序async_write。
在我的客户端和服务器,当客户端连接需要检查消息队列写入和检查,看看是否有任何需要读取的情况。其中一个我有一个困难时期是理解如何做到这一点异步工作的事。
我设想是在async_connect处理器,线程会叫async_write如果有的话是在sendQueue又一遍地打电话async_read。还是应该检查是否有任何可被读取它的前async_read?
下面是什么我谈论的例子。
无效BoostTCPConnection :: connectHandler()
{
setRunning(真);
而(isRunning())
{
//如果发送队列中有消息
如果(sendSize大于0)
{
//拨打async_write
发送();
} 提高:: shared_ptr的&LT;的std ::矢量&lt;&字符GT; &GT; sizeBuffer(新的std ::矢量&lt;&烧焦GT;(4));
提高:: ASIO :: async_read(socket_,提高:: ASIO ::缓冲区(数据大小),提高::绑定(安培; BoostTCPConnection :: handleReceive,shared_from_this(),提振:: ASIO ::占位符::错误sizeBuffer)); }
}无效BoostTCPConnection :: handleReceive(常量的boost ::系统::错误_ code和;错误,提高:: shared_ptr的&LT;的std ::矢量&lt;&字符GT;&GT; sizeBuffer)
{ 如果(错误)
{
//处理错误
返回;
} 为size_t MESSAGESIZE(0);
的memcpy((无效*)(安培; MESSAGESIZE),(无效*)sizeBuffer.data(),4); 提高:: shared_ptr的&LT;的std ::矢量&lt;&字符GT; &GT;消息(新的std ::矢量&lt;&字符GT;(MESSAGESIZE)); //这会给竞争条件与其他读?
//应该经常读发生在这里
提高:: ASIO :: async_read(socket_,提高:: ASIO ::缓冲区(数据大小)
提高::绑定(安培; BoostTCPConnection :: handleReceiveMessage,shared_from_this()
提高:: ASIO ::占位符::错误消息));}无效BoostTCPConnection :: handleReceiveMessage(常量的boost ::系统::错误_ code和;错误,提高:: shared_ptr的&LT;的std ::矢量&lt;&字符GT;&GT; rcvBuffer)
{
如果(错误)
{
//处理错误
返回;
} 提高:: shared_ptr的&LT;标准::字符串&GT;消息(新标准::字符串(rcvBuffer.begin(),rcvBuffer.end()));
receivedMsgs_.push_back(消息);
}无效BoostTCPConnection :: handleWrite(常量的boost ::系统::错误_ code和;错误,为size_t bytes_transferred)
{
//成功
如果(error.value()== 0)
返回;
//其他的HandleError
}
从概念上讲, async_read
等待要接收的数据。你应该把它要在接收后的数据和读是不是已经挂起发生的事情的任何时间。同样, async_write
等待要写入的数据。你应该把它你需要写数据的时间和写是不是已经挂起的。
您应该叫 async_read
当你完成连接。你的 async_read
处理程序返回之前,也许应该叫 async_read
试。
当你需要写的连接,你应该叫 async_write
(如果写尚未待定)。在你的 async_write
的处理程序,如果你还需要多写,你应该叫 async_write
试。
如果没有读取已暂停,你可以叫 async_read
在你写的处理程序,如果你想继续你写完后阅读。您也可以只保留一个读始终悬而未决。这是给你的。
您不应该检查是否有什么事叫 async_read
前必读。 async_read
的一点是它完成时,有东西可以读。这是在此期间等待和做其他事情一个聪明的办法。
I'm having a hard time understand the correct way I should structure a tcp client when using async_read and async_write. The examples seem to do a async_read after connecting and then have async_write in the handler.
In the case of my client and sever, when the client connects it needs to check a queue of messages to write and check to see if anything needs to be read. One of the things I'm having a hard time with is understanding how this would work asynchronously.
What I envision is in the async_connect handler, the thread would call async_write if anything is in the sendQueue and call async_read over and over. Or should it check if anything is available to be read before it does an async_read? Below is an example of what I'm talking about.
void BoostTCPConnection::connectHandler()
{
setRunning(true);
while (isRunning())
{
//If send Queue has messages
if ( sendSize > 0)
{
//Calls to async_write
send();
}
boost::shared_ptr<std::vector<char> > sizeBuffer(new std::vector<char>(4));
boost::asio::async_read(socket_, boost::asio::buffer(data, size), boost::bind(&BoostTCPConnection::handleReceive, shared_from_this(), boost::asio::placeholders::error, sizeBuffer));
}
}
void BoostTCPConnection::handleReceive(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > sizeBuffer)
{
if (error)
{
//Handle Error
return;
}
size_t messageSize(0);
memcpy((void*)(&messageSize),(void*)sizeBuffer.data(),4);
boost::shared_ptr<std::vector<char> > message(new std::vector<char>(messageSize) );
//Will this create a race condition with other reads?
//Should a regular read happen here
boost::asio::async_read(socket_, boost::asio::buffer(data, size),
boost::bind(&BoostTCPConnection::handleReceiveMessage, shared_from_this(),
boost::asio::placeholders::error, message));
}
void BoostTCPConnection::handleReceiveMessage(const boost::system::error_code& error, boost::shared_ptr<std::vector<char> > rcvBuffer)
{
if (error)
{
//Handle Error
return;
}
boost::shared_ptr<std::string> message(new std::string(rcvBuffer.begin(),rcvBuffer.end()));
receivedMsgs_.push_back(message);
}
void BoostTCPConnection::handleWrite(const boost::system::error_code& error,size_t bytes_transferred)
{
//Success
if (error.value() == 0)
return;
//else handleError
}
Conceptually, async_read
waits for data to be received. You should call it any time you want something to happen after data is received and a read isn't already pending. Similarly, async_write
waits for data to be written. You should call it any time you need to write data and a write isn't already pending.
You should call async_read
when you complete the connection. Before your async_read
handler returns, it should probably call async_read
again.
When you need to write to the connection, you should call async_write
(if a write isn't already pending). In your async_write
handler, if you still need to write more, you should call async_write
again.
If no read is already pending, you can call async_read
in your write handler, if you wish to resume reading after you finish writing. You can also just keep a read always pending. That's up to you.
You should not check if there's anything to read before calling async_read
. The point of async_read
is for it to complete when there's something to read. It's a smart way of waiting and doing other things in the meantime.
这篇关于有一个很难理解与升压ASIO TCP一些概念与async_read和async_write的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!