Pergunta

Eu tenho uma estrutura de dados que se parece com isso:

typedef struct
{
  unsigned short m_short1;
  unsigned short m_short2;
  unsigned char m_character;
} MyDataType;

Eu quero usar boost :: serialização para serializar esta estrutura de dados, então use boost :: asio para transmiti-la via TCP / IP, em seguida, ter outra aplicação receber os dados e de-serialize-la usando o mesmo impulso bibliotecas.

Estou tentando seguir boost :: serialização tutorial , ( como alguns outros SO perguntas sugeriram ), mas o exemplo é especificamente para escrita / leitura de um arquivo, não a uma tomada usando boost :: asio.

Eu tenho certeza que eu tenho as ferramentas certas para o trabalho - Eu só preciso de ajuda fazê-los trabalhar juntos. Escrevendo para um soquete não pode ser tão diferente de escrever para um arquivo, certo?

Todas as sugestões são muito apreciados. Obrigado!

Foi útil?

Solução

Para tal estrutura simples, boost :: serialização é um exagero e sobrecarga enorme.

Do mais simples:

vector<uint16_t> net(3,0);

net[0]=htons(data.m_short1);
net[1]=htons(data.m_short2);
net[2]=htons(data.character);

asio::async_write(socket,buffer((char*)&net.front(),6),callback);

vector<uint16_t> net(3,0);
asio::async_read(socket,buffer((char*)&net.front(),6),callback);

callback:
data.m_short1=ntohs(net[0]);
data.m_short2=ntohs(net[1]);
data.character=ntohs(net[2]);

e salve-se sobrecarga enorme que boost :: serialização tem

E se você protocolo privado onde os computadores com a mesma ordem de bytes de trabalho (grande / pequeno) que só estrutura de envio, como é -. POD

Outras dicas

Há uma boa serialização exemplo na documentação asio: server.cpp , stock.hpp , connection.hpp .

Aqui está um trecho:

std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
archive << your_struct;
outbound_data_ = archive_stream.str();
boost::asio::async_write(socket_, 
    boost::asio::buffer(outbound_data_), handler);

Eu pensei em compartilhar isso com alguém que estava tentando serializar um struct C ++ usando Boost. Para o exemplo dado acima, para fazer a serializável struct você adicionar uma função serialize:

typedef struct
{
  unsigned short m_short1;
  unsigned short m_short2;
  unsigned char m_character;

  template <typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  {
    ar & m_short1;
    ar & m_short2;
    ar & m_character;
  }
} MyDataType;

EDIT: Eu retiro minha resposta abaixo, o que eu proposto tem as vantagens de tempo e espaço sobre a solução stringstream mas a API asio :: fluxo está faltando alguma funcionalidade importante que será necessário em um longo prazo (por exemplo cronometrado interrupção ).


A minha resposta original:

Use fluxos de boost :: asio, tem tempo e espaço vantagens sobre escrevê-lo em std :: stringstreams e, em seguida, enviá-lo de uma só vez. Aqui está como:

O código do cliente:

boost::asio::ip::tcp::iostream stream("localhost", "3000");

if (!stream)
  throw std::runtime_error("can't connect");

código do servidor:

boost::asio::io_service ios;
boost::asio::ip::tcp::endpoint endpoint
  = boost::asio::ip::tcp::endpoint(ip::tcp::v4(), 3000);
boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
boost::asio::ip::tcp::iostream stream;

// Your program stops here until client connects.
acceptor.accept(*stream.rdbuf()); 

E então, depois que você está conectado com qualquer fluxo de cliente ou servidor apenas fazer:

MyDataType obj;

// Send the object.
boost::archive::text_oarchive archive(stream);
archive << obj;

// Or receive it.
boost::archive::text_iarchive archive(stream);
archive >> obj;

Você de necessidade curso para adicionar a função 'serialize' em seu MyDataType como Tymek escreveu em sua resposta.

Você fazendo serialização para boost :: arquivo que obter parâmetro de construtor - fluxo de destino, onde irá guardar dados. Você poderia usar boost.iostreams biblioteca para definir o seu próprio fluxo que irá enviar dados através da rede, em vez de arquivos ou simplesmente usar ASIO fluxos de soquete ( http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/reference/ip__tcp/iostream.html ). É uma boa maneira, nós fizemos algo semelhante a este, mas temos alguns riachos (zip / criptografar / Send) e boost usado iostreams biblioteca para toda a operação.

Fácil e modo fictício - armazenar seus dados em arquivo temporário e envia este arquivo:)

Os arquivos impulso de serialização pode ser construído com qualquer fluxo. Assim, qualquer oarchive pode usar qualquer ostream e qualquer iarchive pode usar qualquer istream. Assim, você pode arquivar a um ostringstream, transmitir a corda com ASIO, e reconstruir os dados a partir daí.

Consulte a referência de binary_oarchive aqui , por exemplo.

Eu suspeito que você vai querer arquivar para a memória primeiro, e depois escrever isso para o socket.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top