2013-05-18 1 views
1

J'ai des difficultés à trouver la bonne façon d'utiliser boost sérialisation/asio pour envoyer des objets sur le réseau. La classe message est aussi simple que possible. Ce n'est pas C++ sympa ni adapté à mes besoins, je viens de rester simple temporairement pour tester ASIO/ser:Échec de la sérialisation des données binaires en boost avec l'erreur `signature invalide '

class message { 
    friend class boost::serialization::access; 
public: 
    message(){} 
    int type; 
    int sender; 
    int assignment; 
    int nogood; 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar & type; 
     ar & sender; 
     ar & assignment; 
     ar & nogood; 
    } 
}; 

Du côté client lorsque l'agent décide d'envoyer un message, envoie au serveur via sa connexion tcp:

message m; 
// do something to generate message 
boost::asio::streambuf bufx; 
std::ostream os(&bufx); 
boost::archive::binary_oarchive ar(os); 
ar & m; 
boost::asio::write(socket, bufx); 

code côté serveur:

boost::asio::streambuf bufx; 
std::istream is(&bufx); 
boost::archive::binary_iarchive ia(is); // <--- Exception: invalid signature 
size_t rcx = asio::read(socket,bufx); 
message m; 
ia >> m; 

Répondre

1

Dans votre code côté serveur, votre streambuf est vide lorsque vous créez l'archive binaire. Si le constructeur d'archives recherche un nombre magique au début de l'archive, il ne le trouvera pas. Essayez de remplir le streambuf avec l'appel à boost::asio::read()avant en construisant le flux et l'archive.

+0

Tanks pour votre réponse. J'ai déplacé 'read()' immédiatement après la définition de 'streambuf'. Maintenant, read jette une exception avec ce message: 'End of file' –

+1

Je crois que c'est prévu. 'read()' bloque jusqu'à ce que le tampon soit plein ou qu'une erreur survienne. Dans ce cas, "l'erreur" est que le socket s'est fermé. Vous pouvez utiliser la commande 'read()' [overload] (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/read/overload6.html) qui renvoie le statut via un argument de référence 'boost :: system :: error_code' au lieu de lancer une erreur. – rhashimoto

1

J'ai la même exception.

Et This official example m'aide.

Si vous avez encore des problèmes, essayez ceci.

size_t n = sock.receive(bufs); 

// received data is "committed" from output sequence to input sequence 
b.commit(n); 

std::istream is(&b); 
std::string s; 
is >> s; 

Dans mon cas, j'utilise async_read. En fait, j'ai modifié le example.

boost::asio::streambuf inbound_; 
    boost::asio::streambuf::mutable_buffers_type bufs = inbound_.prepare(inbound_data_size); 
    void (connection::*f)(
     const boost::system::error_code&, std::size_t, 
     T&, boost::tuple<Handler>) 
    = &connection::handle_read_data<T, Handler>; 
    boost::asio::async_read(socket_, boost::asio::buffer(bufs), 
    boost::bind(f, this, 
     boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(t), handler)); 

Et puis au gestionnaire

/// Handle a completed read of message data. 
    template <typename T, typename Handler> 
    void handle_read_data(const boost::system::error_code& e, std::size_t bytes_transferred, 
     T& t, boost::tuple<Handler> handler) 
    { 
    if (e) 
    { 
     boost::get<0>(handler)(e); 
    } 
    else 
    { 
     // Extract the data structure from the data just received. 
     try 
     { 
     inbound_.commit(bytes_transferred); 
     std::istream archive_stream(&inbound_); 
     boost::archive::binary_iarchive archive(archive_stream); 
     archive >> t; 
     } 
     catch (std::exception& err) 
     { 
     // Unable to decode data. 
     boost::system::error_code error(boost::asio::error::invalid_argument); 
     boost::get<0>(handler)(error); 
     return; 
     } 

     // Inform caller that data has been received ok. 
     boost::get<0>(handler)(e); 
    } 
    } 
Questions connexes