Arbeiten mit boost::asio::streambuf
Suchen für ein boost::asio (und mit sich selbst steigern) beschlossen, das schreiben asynchronen server. Zum speichern von eingehenden Daten nutze ich boost::asio::streambuf.
Hier habe ich ein problem. Wenn ich eine zweite Nachricht von dem client und anschließende sehe ich, dass der Puffer enthält Daten aus vorherigen Nachrichten.
Obwohl ich call Verbrauchen-Methode mit der input-buffer. Was ist falsch?
class tcp_connection
//Using shared_ptr and enable_shared_from_this
//because we want to keep the tcp_connection object alive
//as long as there is an operation that refers to it.
: public boost::enable_shared_from_this<tcp_connection>
{
...
boost::asio::streambuf receive_buffer;
boost::asio::io_service::strand strand;
}
...
void tcp_connection::receive()
{
//Read the response status line. The response_ streambuf will
//automatically grow to accommodate the entire line. The growth may be
//limited by passing a maximum size to the streambuf constructor.
boost::asio::async_read_until(m_socket, receive_buffer, "\r\n",
strand.wrap(boost::bind(&tcp_connection::handle_receive, shared_from_this()/*this*/,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
void tcp_connection::handle_receive(const boost::system::error_code& error,
std::size_t bytes_transferred)
{
if (!error)
{
//process the data
/* boost::asio::async_read_until remarks
After a successful async_read_until operation,
the streambuf may contain additional data beyond the delimiter.
An application will typically leave that data in the streambuf for a
subsequent async_read_until operation to examine.
*/
/* didn't work
std::istream is(&receive_buffer);
std::string line;
std::getline(is, line);
*/
//clean up incomming buffer but it didn't work
receive_buffer.consume(bytes_transferred);
receive();
}
else if (error != boost::asio::error::operation_aborted)
{
std::cout << "Client Disconnected\n";
m_connection_manager.remove(shared_from_this());
}
}
InformationsquelleAutor vint | 2015-02-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entweder mit einem
std::istream
und Lesen, wie durchstd::getline()
, oder explizit aufrufenboost::asio::streambuf::consume(n)
, entfernen Sie die Daten aus der Eingabe-Sequenz.Wenn die Anwendung ausgeführt werden, entweder diesen und die nachfolgenden
read_until()
Operationen Ergebnisse in doppelte Datensätze inreceive_buffer
's input-Sequenz, dann den duplizierten Daten ist wahrscheinlich, die aus der Gegenstelle. Wenn der remote-peer ist schriftlich an die Steckdose und direkt über ein streambuf - input-Folge, dann ist die Gegenstelle muss explizit aufgerufenconsume()
nach jeder erfolgreichen Schreibvorgang.Wie bereits in der Dokumentation, erfolgreiche
read_until()
Operationen enthalten können zusätzliche Daten über die Trennzeichen, einschließlich zusätzliche Trennzeichen. Zum Beispiel, wenn"a@b@"
geschrieben, ein sockel, einread_until()
Betrieb mit'@'
als Trennzeichen Lesen und verpflichten"a@b@"
zu den streambuf input-Sequenz. Jedoch wird der Betrieb zeigen, dass die Menge der bytes, die übertragen ist, bis zu und einschließlich der ersten Trennzeichen. Sobytes_transferred
wäre2
undstreambuf.size()
wäre4
. Nach2
bytes verbraucht sind, die streambuf - input-Sequenz enthalten"b@"
, und ein anschließender Aufruf vonread_until()
sofort zurück, als der streambuf bereits das Trennzeichen enthält.Hier ist ein vollständiges Beispiel demonstrieren
streambuf
- Nutzung für das Lesen und schreiben, und wie die Eingabe-Reihenfolge verbraucht wird:Ausgabe:
Super, sehr hilfreiche Antwort. Ich möchte die Boost-Leute hätte es schreiben Sie alle Ihre Unterlagen! 😉
Wie hast du den Zugriff auf die input-Sequenz, ohne jemals Begehen (
commit()
)? data () - Dokumentation, sagtdata()
Retouren-Liste der Eingabe-Puffer und nach commit () - Dokumentation, es tatsächlich kopiert die Zeichen aus der Ausgabe-Reihenfolge nach Eingangs-Reihenfolge.Bei der Verwendung von Asio Operationen akzeptieren, dass die
streambuf
(nicht einen Puffer darstellt, die auf der its Sequenzen), oder bei der Verwendung von stream-Objekten, die mit einemstreambuf
wiestd::ostream
, die zugrunde liegenden input-und output-Sequenzen werden richtig verwaltet. Antwort bieten weitere details. Auch die Dokumentation fürcommit()
erwähnt bewegen, nicht kopieren, Daten. Die aktuelle Implementierung verwendet einen einzigen zusammenhängenden array, wo einecommit()
Fortschritte sowohl der Ausgabe-Reihenfolge beginnen Zeiger und input-sequence-end-Zeiger vonn
Zeichen.danke für die schnelle Antwort. Da die Frage etwas älter ist, ich hatte erwartet, ein wenig länger warten.
InformationsquelleAutor Tanner Sansbury