2010-08-30 17 views

Répondre

5

Typiquement, j'utilise boost::asio::streambuf pour les structures sérialisantes.

Message.h

#ifndef MESSAGE_H 
#define MESSAGE_H 

#include <boost/serialization/string.hpp> 

#include <string> 

struct Message 
{ 
    std::string _a; 
    std::string _b; 

    template <class Archive> 
    void serialize(
      Archive& ar, 
      unsigned int version 
      ) 
    { 
     ar & _a; 
     ar & _b; 
    } 
}; 

#endif 

client.cpp

#include "Message.h" 

#include <boost/archive/text_oarchive.hpp> 

#include <boost/asio.hpp> 

int 
main() 
{ 
    Message msg; 
    msg._a = "hello"; 
    msg._b = "world"; 

    boost::asio::streambuf buf; 
    std::ostream os(&buf); 
    boost::archive::text_oarchive ar(os); 
    ar & msg; 

    boost::asio::io_service io_service; 
    boost::asio::ip::tcp::socket socket(io_service); 
    const short port = 1234; 
    socket.connect(
      boost::asio::ip::tcp::endpoint(
       boost::asio::ip::address::from_string("127.0.0.1"), 
       port 
       ) 
      ); 

    const size_t header = buf.size(); 
    std::cout << "buffer size " << header << " bytes" << std::endl; 

    // send header and buffer using scatter 
    std::vector<boost::asio::const_buffer> buffers; 
    buffers.push_back(boost::asio::buffer(&header, sizeof(header))); 
    buffers.push_back(buf.data()); 
    const size_t rc = boost::asio::write(
      socket, 
      buffers 
      ); 
    std::cout << "wrote " << rc << " bytes" << std::endl;; 
} 

server.cpp

#include "Message.h" 

#include <boost/archive/text_iarchive.hpp> 

#include <boost/asio.hpp> 

int 
main() 
{ 
    boost::asio::io_service io_service; 
    const uint16_t port = 1234; 
    boost::asio::ip::tcp::acceptor acceptor(
      io_service, 
      boost::asio::ip::tcp::endpoint(
       boost::asio::ip::address::from_string("127.0.0.1"), 
       port 
       ) 
      ); 

    boost::asio::ip::tcp::socket socket(io_service); 
    acceptor.accept(socket); 
    std::cout << "connection from " << socket.remote_endpoint() << std::endl; 

    // read header 
    size_t header; 
    boost::asio::read(
      socket, 
      boost::asio::buffer(&header, sizeof(header)) 
      ); 
    std::cout << "body is " << header << " bytes" << std::endl; 

    // read body 
    boost::asio::streambuf buf; 
    const size_t rc = boost::asio::read(
      socket, 
      buf.prepare(header) 
      ); 
    buf.commit(header); 
    std::cout << "read " << rc << " bytes" << std::endl; 

    // deserialize 
    std::istream is(&buf); 
    boost::archive::text_iarchive ar(is); 
    Message msg; 
    ar & msg; 

    std::cout << msg._a << std::endl; 
    std::cout << msg._b << std::endl; 
} 
+0

Je pense que cela fonctionnera bien avec l'envoi des données. Est-ce que cela fonctionne également avec la lecture des données de socket? Ici, nous ne savons pas à l'avance la taille des chaînes entrantes. – Canopus

+0

oui, vous devrez envoyer un en-tête de longueur fixe indiquant la taille du tampon. –

+0

J'ai mis à jour ma réponse montrant comment envoyer un en-tête –