Mein Programm fungiert als Server, zu dem ein Client eine Verbindung herstellen kann. Sobald ein Client verbunden ist, erhält er alle 5 Sekunden Updates vom Server. Dies ist die write
-function, die alle 5 Sekunden zu senden und die neuen Daten an den Client aufgerufen wird:Boost.Asio: Zeitüberschreitung für asynchrone Vorgänge
void NIUserSession::write(std::string &message_orig)
{
std::cout << "Writing message" << std::endl;
std::shared_ptr<std::string> message = std::make_shared<std::string>(message_orig);
message->append("<EOF>");
boost::system::error_code ec;
boost::asio::async_write(this->socket_, boost::asio::buffer(*message),
boost::asio::transfer_all(), boost::bind(&NIUserSession::writeHandler,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred(),
message
));
}
void NIUserSession::writeHandler(const boost::system::error_code &error, std::size_t bytes_transferred, std::shared_ptr<std::string> message)
{
std::cout << "Write Handler" << std::endl;
if(error)
{
std::cout << "Write handler error: " << error.message() << std::endl;
this->disconnect();
}
}
void NIUserSession::disconnect()
{
std::cout << "Disconnecting client, cancling all write and read operations." << std::endl;
this->socket_.lowest_layer().cancel();
delete this;
}
Wenn ein Fehler in den Schreiboperationen ist die Verbindung zwischen dem Server und dem Client geschlossen wird und alle Asynchron Operationen sind cancled (this->socket_.lowest_layer().cancel();
).
Das Problem ist, dass wenn die Verbindung abläuft, writeHandler
nicht sofort aufgerufen wird. Stattdessen "stapeln" die Schreiboperationen, bis die erste writeHandler
erreicht.
Dies sollte die normale Ausgabe des Programms sein:
Writing message
Write Handler
... Other stuff ...
... Other stuff ...
Writing message
Write Handler
Wenn die Verbindungen mal aus, das ist, was passiert:
Writing message
Write Handler
Write handler error: Connection timed out
Disconnecting client, cancling all write and read operations.
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Segmentation fault
Am Ende steigt ein Segmentierungsfehler. Ich denke, das ist, weil disconnect
aufgerufen wird, während andere asynchrone Operationen noch auf ihrem Weg sind. Ich dachte, ich könnte es vermeiden, indem Sie this->socket_.lowest_layer().cancel();
direkt nach der ersten asynchronen Operation fehlschlägt, aber es funktioniert nicht.
Wie kann ich einen Segmentierungsfehler vermeiden?
Es führt nicht zu einem Segmentierungsfehler. Es führt zu [Undefined Behaviour] (https://en.wikipedia.org/wiki/Undefined_behavior). Sonst, +1 – sehe
Sie müssen bei der Verwendung von asynchronen Operationen sehr vorsichtig mit Objektlebensdauern umgehen. Die 'boost :: asio' [Beispiele] (http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/examples/cpp11_examples.html) verwenden' shared_ptr' aus gutem Grund, siehe: [ boot asio async-funktion und shared ptrs] (http://stackoverflow.com/questions/11356742/boost-async-functions-and-shared-ptrs/19622084#19622084) – kenba
@sehe - danke, bearbeitet :) Mein schlechtes für die Verwendung die falsche Formulierung. –