boost :: asio :: async_read_until lit toutes les données au lieu de seulement
Je suis de modifier le Boost Asio écho exemple l'utilisation de async_read_until
pour lire l'entrée de mot en mot. Même si je suis en utilisant async_read_until
toutes les données envoyées semble être lue à partir du socket. Quelqu'un pourrait-veuillez indiquer:
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
{
public:
session(boost::asio::io_service& io_service)
: socket_(io_service)
{
}
tcp::socket& socket()
{
return socket_;
}
void start()
{
std::cout<<"starting"<<std::endl;
boost::asio::async_read_until(socket_, buffer, ' ',
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
std::ostringstream ss;
ss<<&buffer;
std::string s = ss.str();
std::cout<<s<<std::endl;
if (!error)
{
boost::asio::async_write(socket_,
boost::asio::buffer(s),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error));
}
else
{
delete this;
}
}
void handle_write(const boost::system::error_code& error)
{
std::cout<<"handling write"<<std::endl;
if (!error)
{
}
else
{
delete this;
}
}
private:
tcp::socket socket_;
boost::asio::streambuf buffer;
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session* new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
void handle_accept(session* new_session,
const boost::system::error_code& error)
{
if (!error)
{
new_session->start();
new_session = new session(io_service_);
acceptor_.async_accept(new_session->socket(),
boost::bind(&server::handle_accept, this, new_session,
boost::asio::placeholders::error));
}
else
{
delete new_session;
}
}
private:
boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
using namespace std; //For atoi.
server s(io_service, atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
source d'informationauteur user368831
Vous devez vous connecter pour publier un commentaire.
Lire la description de async_read_until soigneusement. Il dit:
Ce que cela signifie dans votre cas est que l'intérieur handle_read(), vous devez accéder à la première
bytes_transferred
octets de la mémoire tampon. A partir de maintenant, votrebytes_transferred
paramètre n'est pas utilisé.La réponse par Cubbi est correct:
async_read_until()
peut lire des données supplémentaires dans la mémoire tampon.L'autre réponse par ecoretchi est un peu dangereux. Il n'est pas incorrect, mais ne fonctionne que de travailler cette question spécifique, qui se lit d'entrée de mot par mot (jusqu'à
' '
).Si vous êtes à la lecture de la ligne de saisie en ligne (jusqu'à
'\n'
), vous risquez de perdre des données avec cette solution. Cela arrive parce que si vous utilisezcommit()
et >> opérateur divise vos données à autre chose que le retour à la ligne (par exemple, vous avez des numéros et des espaces dans les données) toutes les données sont perdues.Lors de la lecture ligne par ligne, vous devez utiliser
getline()
pour obtenir une ligne de la mémoire tampon. Ce qui laisse le reste des données en attente dans lastreambuf
classe et vous permet de lire avec les appels suivants. C'est aussi la raison pour laquelle vous devez avoir lestreambuf
comme une variable membre, non pas comme une variable locale dans une fonction; si c'est une variable locale, toutes les données supplémentaires au-delà de la première ligne serait perdu.C'est par la conception. Asio n'a pas de bon endroit pour stocker des données en excès, de sorte qu'il les gère pour vous. Asio n'est pas parser, jetez un oeil à boost::spirit, ou faire l'analyse ad hoc, à l'instar de nos ancêtres. 🙂
Essayez ceci: