[boost::asio] Reihenfolge von Schreiboperationen bei boost::async_write()
-
Moin,
angenommen ich mache irgendetwas in der Art:
void f(tcp::socket& socket, std::string buffer_1, std::string buffer_2) { async_write(socket, buffer(buffer_1), ... ); async_write(socket, buffer(buffer_2), ...); }Kann ich dann davon ausgehen, dass zuerst alles aus buffer_1 bei der
Gegenseite ankommt und dann erst Inhalte von buffer_2 oder muss
ich davon ausgehen, dass buffer_1[0], buffer_2[0], buffer_1[1] o.ä.
auf der Gegenseite ankommen?Was passiert, wenn es einen Fehler bei der Übertragung des ersten Buffers gibt?
Muss ich mir, um die Reihenfolge zu garantieren, eine Queue bauen und
den nächsten Aufruf von async_write erst absetzen, wenn der letzte
fertig ist?Gruß, Panke
-
Hallo Panke!
boost::asio::async_write setzt voraus, dass deine Buffer Götter sind bzw. lang leben, lang genug bis der completion_handler aufgerufen wird.
Du hast hier aber 2 lokale Buffer:
boost::asio::async_write kehrt aber sofort nach dem Funktionsaufruf zurück und wenn dann der completion_handler in den Buffer etwas reinschreiben will crashed dein Programm, wegen einer Speicherzugriffsverletzung.ERGO: Du musst deinen Buffer am Heap platzieren oder du hast eine Membervariable, like:
class Connection { std::string mBuffer; // lebt lang genug public: void send(const std::string &message) { mBuffer = message; using namespace boost::asio; async_write(socket_, buffer(mBuffer),...); } };Weiters habe ich die boost::asio Doku so verstanden, dass während einer write-operation keine weitere write-operation ausgeführt werden darf.(das selbe gilt auch für eine read-operation):
This operation is implemented in terms of zero or more calls to the stream's async_write_some function, and is known as a composed operation. The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.
This operation is implemented in terms of zero or more calls to the stream's async_read_some function, and is known as a composed operation. The program must ensure that the stream performs no other read operations (such as async_read, the stream's async_read_some function, or any other composed operations that perform reads) until this operation completes.
Ja, du musst dir also eine Queue bauen, siehe das Chat-Example von boost::asio.
Jeder deiner completion_handler bekommt eine error Variable.
void read_handler(const boost::asio::system::error_code &error) { if(!error) { // Kein Error, alles hat funktioniert. // lese den buffer aus } else { // UPS! std::cerr << "[read_handler()]: " << error.message() << std::endl; } }boost::asio bzw. asynchrone Bibliotheken sind sehr eigen in ihrer Verwendung.
Schau dir ein paar examples an, versuch das Prinzip dahinter zu verstehen, dann solltest du keine Schwierigkeiten mehr haben.Ich selbst habe hier im Forum einige Threads bzgl. Boost::asio aufgemacht, such mal hier.
-
Weiters habe ich die boost::asio Doku so verstanden, dass während einer write-operation keine weitere write-operation ausgeführt werden darf.(das selbe gilt auch für eine read-operation):
Dafür würde es noch die Scattered Buffer geben...
-
AmITrolling? schrieb:
Hallo Panke!
[alles über die Lebendauer von Puffern]
Danke, das weiß ich. Da habe ich nur hier im Forum gepennt.
This operation is implemented in terms of zero or more calls to the stream's async_write_some function, and is known as a composed operation. The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.
This operation is implemented in terms of zero or more calls to the stream's async_read_some function, and is known as a composed operation. The program must ensure that the stream performs no other read operations (such as async_read, the stream's async_read_some function, or any other composed operations that perform reads) until this operation completes.
Ja, du musst dir also eine Queue bauen, siehe das Chat-Example von boost::asio.
Danke, das sind genau die Stellen in der Doku, die ich suchte

-
Wie ist das denn, wenn ich die Memberfunktionen des UDP-Sockets benutze?
Also async_receive_from
und async_send_toIch arbeite an einem Spiel und muss mit mehreren Clients kommunizieren können.
Kann ich da mit async_send_to gleichzeitig zu mehreren Empfängern senden, oder muss ich warten, bis der erste Sendvorgang fertig ist, bevor ich den zweiten starte (was sehr schlecht wäre).
Und bei async_receive_from habe ich mir überlegt, dass ungefähr so zu machen:
void NetworkServer::onReadFinished(const boost::system::error_code& error, std::size_t bytesTransferred) { //mache was mit den empfangen daten... //starte den nächsten empfang-Vorgang mySocket.async_receive_from(buffer(myReadBuffer), myRemoteEndpointStorage, 0, boost::bind(&NetworkServerImpl::onReadFinished, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void NetworkServer::update() { while(myIoService.poll() > 0) ; }In der Hoffnung, dass dann der completion handler (onReadFinished) mehrfach ausgerufen wird, weil mehrere Nachrichten sofort empfangen werden können, weil sie eigentlich schon da sind und in irgendwelchen Buffern von boost oder dem OS warten...
Was meint ihr, geht das so? Oder geht das vll noch besser?
-
In der Hoffnung, dass dann der completion handler (onReadFinished) mehrfach ausgerufen wird, weil mehrere Nachrichten sofort empfangen werden können, weil sie eigentlich schon da sind und in irgendwelchen Buffern von boost oder dem OS warten...
Das solle gehen, ja. Auch das gleichzeitige senden sollte funktionieren, jedenfalls finde ich nichts Gegenteiliges in der Doku.