提升 TCP async_receive_some不会第二次读取

Boost TCP async_receive_some doesn't read second time

本文关键字:第二次 读取 receive TCP async 提升 some      更新时间:2023-10-16

我尝试拥有一个tcp-server,它正在读取数据,处理它们并将其发送回。之后,它将等待新数据。我的问题是,该服务器首次发送数据正常运行。在第二次,该程序停留在run_one() -loop。

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));
        }
    }
}

在您的接收处理程序中,只有在有问题(?)

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));
    }
}

在此回调上,您需要排队下一个读取(通常没有问题,当有问题时不要!)

除了NIM回答的内容外,您还进行了经典的ASIO错误。如下所示:http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/reference/io_service/run_one_one/run_one/overload1.html"除非有事先调用reset(),否则将立即返回run(),run_one(),poll_one()的后续呼叫()。"

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

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

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