Promuovi Asio async_read non smette di leggere?
-
08-07-2019 - |
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?
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.