Domanda

Ho giocato con le funzioni e le prese di Boost asio (in particolare la lettura / scrittura asincrona). Ora, ho pensato che boost :: asio :: async_read ha chiamato il gestore solo quando è arrivato un nuovo buffer dalla connessione di rete ... tuttavia non smette di leggere lo stesso buffer e quindi continua a chiamare il gestore. Sono stato in grado di mitigarlo controllando il numero di byte trasferiti, tuttavia è sostanzialmente in un ciclo di attesa che spreca cicli di CPU.

Ecco quello che ho:

class tcp_connection : : public boost::enable_shared_from_this<tcp_connection> 
{
public:
    // other functions here

    void start()
    {
    boost::asio::async_read(socket_, boost::asio::buffer(buf, TERRAINPACKETSIZE),
        boost::bind(&tcp_connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }

private:
    const unsigned int TERRAINPACKETSIZE = 128;
    char buf[TERRAINPACKETSIZE];


    void handle_read(const boost::system::error_code& error, size_t bytesT)
    {
        if (bytesT > 0)
        { 
             // Do the packet handling stuff here
        }

        boost::asio::async_read(socket_, boost::asio::buffer(buf, TERRAINPACKETSIZE),
        boost::bind(&tcp_connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    }
};

Alcune cose vengono tagliate, ma fondamentalmente viene creata una nuova connessione, quindi viene chiamato start () . C'è qualcosa che mi manca in modo che il metodo handle_read non venga continuamente chiamato?

È stato utile?

Soluzione

Un'ipotesi selvaggia: controlli errore in handle_read ? Se il socket si trova in uno stato di errore per qualche motivo, suppongo che la chiamata nidificata a async_read fatta da handle_read verrà immediatamente " completata " ;, risultante in una chiamata immediata a handle_read

Altri suggerimenti

Stavo avendo lo stesso problema. Nel mio caso, stavo leggendo in uno std :: vector in questo modo:

boost::asio::async_read(socket_,
st::asio::buffer(*message,message->size()),
            boost::bind(
              &ActiveSocketServerSession::handleFixLengthRead,
              shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred)
    );

Ho un vettore adattativo per accettare un numero variante di byte

    std::vector<unsigned char>* message;
message = new std::vector<unsigned char> (sizePacket);

Quando stavo ricevendo il primo pacchetto tutto andava bene, ma dopo il primo non smetteva mai di sbloccare handle_reader senza dati.

La mia soluzione era eliminare il mio vettore e allocare nuovamente lo spazio dopo averlo elaborato:

void ActiveSocketServerSession::handleFixLengthRead(    const         boost::system::error_code& error,
                                                    std::size_t bytes_transferred){

    --> processing your data (save to another site)
--> delete message;
--> message = new std::vector<unsigned char> (sizePacket);

//starting to read again
boost::asio::async_read(socket_,
                boost::asio::buffer(*message,message->size()),
            boost::bind(
              &ActiveSocketServerSession::handleFixLengthRead,
              shared_from_this(),
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred)
);

    }else{
        logMessage.str("");
        logMessage << "Error handling data id: "<<getId()<< "from port";
    }
}

Ho trovato questa soluzione leggendo questo

Dopo aver inserito queste due righe va tutto bene.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top