Boost TCP async_receive_some不会再次读取

时间:2014-01-22 11:52:51

标签: c++ asynchronous tcp boost-asio

我尝试使用TCP-Server,它正在读取数据,处理它们并将它们发回。之后它将等待新的数据。我的问题是,服务器第一次发送数据时工作正常。第二次,程序保持在run_one() - 循环。

size_t m_lengthReceive;
io_service m_ioService;
std::vector<unsigned char> m_vectorBuffer;
unsigned char m_bufferReceive[128];


void SyncServer::initialize(){      
        m_acceptor = shared_ptr<tcp::acceptor>(
                new tcp::acceptor(m_ioService,
                        tcp::endpoint(tcp::v4(), m_port)));

        m_acceptor->set_option(tcp::acceptor::reuse_address(true));
        m_sock = shared_ptr<tcp::socket>(new tcp::socket(m_ioService));

        m_acceptor->accept(*m_sock, m_ec);
}

void SyncServer::tcpReceiveVector(){
        boost::system::error_code ec;
        m_sock->async_read_some(buffer(m_bufferReceive),
                boost::bind(&SyncServer::tcpReceiveHandler, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
        do{
            m_ioService.run_one();
        }while(m_lengthReceive == 0);
}


void SyncServer::tcpReceiveHandler(const boost::system::error_code& ec,
        size_t size){
    if(size > 0 && !ec){
        m_sock->cancel();
        m_lengthReceive = size;
        m_vectorBuffer.resize(m_lengthReceive);
        int i = 0;
        for(std::vector<unsigned char>::iterator it = m_vectorBuffer.begin();
                it != m_vectorBuffer.end(); ++it){
            *it = m_bufferReceive[i];
            ++i;
        }
    }else{
        m_lengthReceive = 0;
        m_sock->async_read_some(buffer(m_bufferReceive),
                boost::bind(&SyncServer::tcpReceiveHandler, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
    }
}

std::vector<unsigned char> SyncServer::getVectorBuffer(){
    return m_vectorBuffer;
}

void SyncServer::openConnection(){
    if(!m_sock->is_open())
        m_sock->open(tcp::v4());
    m_lengthReceive = 0;
}

void SyncServer::closeConnection(){
    m_sock->close();

}

main(){
    m_tcpServer = shared_ptr<SyncServer>(new SyncServer(m_tcpPort));
    m_tcpServer->initialize();
    while(1){
        m_tcpServer->openConnection();
        m_tcpServer->tcpReceiveVector();
        vector = m_tcpServer->getVectorBuffer();

        //do something with vector

        m_tcpServer->tcpSend(vector); //this works fine
        m_tcpServer->closeConnection();
    }
}

更新代码:

void SyncServer::tcpReceiveHandler(const boost::system::error_code& ec,
        size_t size){
    if(ec){
        std::cout<< ec << std::endl;
    }else{
        if(size > 0){
            m_sock->cancel();
            m_lengthReceive = size;
            m_vectorBuffer.resize(m_lengthReceive);
            int i = 0;
            for(std::vector<unsigned char>::iterator it = m_vectorBuffer.begin();
                    it != m_vectorBuffer.end(); ++it){
                *it = m_bufferReceive[i];
                ++i;
            }
        }else{
            m_lengthReceive = 0;
            m_sock->async_read_some(buffer(m_bufferReceive),
                    boost::bind(&SyncServer::tcpReceiveHandler, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
        }
    }
}

2 个答案:

答案 0 :(得分:2)

在接收处理程序中,如果出现问题(?)

,则只会触发另一次读取
void SyncServer::tcpReceiveHandler(const boost::system::error_code& ec,
        size_t size){
    if(size > 0 && !ec){
        m_sock->cancel();
        m_lengthReceive = size;
        m_vectorBuffer.resize(m_lengthReceive);
        int i = 0;
        for(std::vector<unsigned char>::iterator it = m_vectorBuffer.begin();
                it != m_vectorBuffer.end(); ++it){
            *it = m_bufferReceive[i];
            ++i;
        }
    }else{
        m_lengthReceive = 0;
        m_sock->async_read_some(buffer(m_bufferReceive),
                boost::bind(&SyncServer::tcpReceiveHandler, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
    }
}

在这个回调中,你需要排队下一次读取(通常是在没有问题的情况下,而不是在出现问题时!)

答案 1 :(得分:1)

除了Nim回答之外,你还做了经典的asio错误。如此处所述:http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/io_service/run_one/overload1.html “对run(),run_one(),poll()或poll_one()的后续调用将立即返回,除非事先调用reset()。”

在您.run_one之后,您需要致电m_ioservice.reset(),否则它将再也无法运行。它只是返回而不是调用任何任何异步操作,因此m_lengthReceive在第一次之后不会改变。

    do{
        m_ioService.run_one();
        m_ioService.reset();
    }while(m_lengthReceive == 0);

这是人们通常不使用run_one()而是使用run()并在最后一个处理程序中启动新的异步操作的原因。在这种情况下,run()不会返回,也不需要reset()