2012-11-09 76 views
3

我很难理解使用async_read和async_write时应该如何构造一个tcp客户端的正确方法。 examples似乎在连接后执行async_read,然后在处理程序中执行async_write。用Async_read和async_write Boost ASIO TCP很难理解几个概念

在我的客户端和服务器的情况下,当客户端连接时,它需要检查要写入的消息队列并检查是否需要读取任何内容。我遇到困难的一件事是了解这将如何异步工作。

我的设想是在async_connect处理程序中,如果sendQueue中有任何内容并反复调用async_read,线程将调用async_write。还是应该检查在执行async_read之前是否有可读的内容?以下是我正在谈论的一个例子。

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 


} 

回答

5

从概念上讲,async_read等待数据被接收。在收到数据并且读取尚未完成之前,您应该随时调用它。同样,async_write等待写入数据。您应该在任何时候调用它来写入数据,并且写入操作尚未完成。

当您完成连接时,应该致电async_read。处理程序返回之前,应该再次调用async_read

当您需要写入连接时,应该调用async_write(如果写入操作尚未完成)。在您的async_write处理程序中,如果您仍需要编写更多,则应再次拨打async_write

如果没有读取已经挂起,您可以在写入处理程序中调用async_read,如果您希望在完成写入后继续阅读。您也可以保持读取始终处于等待状态。这取决于你。

在致电async_read之前,您不应该检查是否有任何要阅读的内容。 async_read的要点是有需要阅读的时候才能完成。在此期间,这是一种等待和做其他事情的聪明方式。

+0

@DavidSchwartz我很难组织代码。一个原因是,读或写可能需要在任何时候完成。在这个同步版本中,我只需要使用一个循环并检查是否需要完成并执行它。我想我很难在异步思考。 –

+1

好吧,阅读很容易。在完成连接时调用'async_read',然后在读取处理程序返回之前再次调用它。写操作有点复杂,但您可以随时调用它两种情况:1)您有要写入的数据。 2)您没有已经挂起的异步写入。 –

+0

@DavidSchwartz谢谢。我差不多有async_read了。但调用async_write有我。如果数据可用并且async_write未处于待处理状态,我应该在连接处理程序中有一个循环吗?我可以使用一个strand来串行写入async_write吗? –

相关问题