2011-02-08 3 views
6

J'ai un serveur qui reçoit une chaîne compressée (compressée avec zlib) d'un client, et j'utilisais async_receive de la bibliothèque boost::asio pour recevoir cette chaîne, il s'avère cependant que il n'y a aucune garantie que tous les octets seront reçus, donc je dois maintenant le changer en async_read. Le problème auquel je suis confronté est que la taille des octets reçus est variable, donc je ne suis pas sûr de savoir comment utiliser async_read sans connaître le nombre d'octets à recevoir. Avec le async_receive j'ai juste un boost::array<char, 1024>, cependant c'est un tampon qui n'est pas nécessairement complètement rempli.boost :: asio async_read garantir que tous les octets sont lus

Je me demandais si quelqu'un pouvait proposer une solution où je pourrais utiliser async_read même si je ne connais pas le nombre d'octets à recevoir à l'avance?

void tcp_connection::start(boost::shared_ptr<ResolverQueueHandler> queue_handler) 
{ 
    if (!_queue_handler.get()) 
     _queue_handler = queue_handler; 

    std::fill(buff.begin(), buff.end(), 0); 

    //socket_.async_receive(boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read, shared_from_this(), boost::asio::placeholders::error)); 
    boost::asio::async_read(socket_, boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read, shared_from_this(), boost::asio::placeholders::error)); 
} 

buff est un boost::array<char, 1024>

Répondre

19

Comment vous attendiez-vous à faire cela en utilisant une autre méthode?

Il y a quelques méthodes générales pour l'envoi de données de tailles variables dans un manoir async:

  1. Par message - ce qui signifie que vous avez une tête qui définit la longueur du message attendu suivi d'un corps qui contient données de la longueur spécifiée.
  2. Par flux - ce qui signifie que vous avez une méthode de repère (et c'est très large) pour savoir quand vous avez un paquet complet.
  3. Par connexion - chaque paquet complet de données est envoyé dans une connexion unique qui est fermée une fois que les données sont complètes.

Ainsi vos données peuvent être analysées, ou une longueur envoyé etc ...

+4

+ 1 bon résumé de quelques solutions possibles –

2

Utilisez async_read_until et créez votre propre match condition, ou modifier le protocole d'envoyer un en-tête dont le nombre d'octets à attendre dans la chaîne compressée.

0

Un paquet IP unique est limitée à une taille MTU de 1500 octets ~, et pourtant vous pouvez télécharger des fichiers de giga-octet-grand à partir de votre site Web préféré et regardez des vidéos au format mégaoctet sur YouTube.

Vous devez envoyer un en-tête indiquant la taille réelle des données brutes, puis recevoir les données par morceaux sur des fragments plus petits jusqu'à ce que vous ayez fini de recevoir tous les octets. Par exemple, lorsque vous téléchargez un fichier volumineux sur HTTP, il y a un champ dans l'en-tête indiquant la taille du fichier: Content-Length:.

Questions connexes