2011-10-16 14 views
8

Recentemente ho deciso di utilizzare boost::asio per i miei socket, ma ora sto riscontrando un problema: la documentazione sembra essere carente.Invio di dati grezzi con write() in boost :: asio

Quello che voglio fare è scrivere una funzione che invierà un messaggio costituito dalla seguente struttura:

  • 2 byte di un intero senza segno (uint16_t) per un codice operativo tutti i byte
  • tutti i byte dopo che (una quantità flessibile) è un qualsiasi tipo di dati (castato a void*). Questi dati verranno operati sulla base del codice operativo

Ad esempio, se il codice operativo è 1, forse definito come OPCODE_LOGIN, i byte seguenti dell'opcode potrebbe contenere una stringa contenente dati di accesso, ecc

bool sendMessage(tcp::socket* sock, uint16_t opcode, void* data) 
{ 
    void* fullData = malloc(sizeof(uint16_t) + sizeof(data)); 
    memcpy(fullData, (void*)opcode, sizeof(opcode)); 
    memcpy(&fullData + sizeof(uint16_t), data, sizeof(data)); 
    boost::asio::write(sock, boost::asio::buffer(fullData, sizeof(fullData))); 
    // by the way, at this point, is it safe to delete fullData to prevent memory leaks? 
    return true; 

}

Questo non viene tuttavia compilato. Ottengo un errore di compilazione criptico per quanto riguarda la chiamata a scrivere:

1>------ Build started: Project: client, Configuration: Debug Win32 ------ 
1> main.cpp 
1>c:\boost\boost_1_47\boost\asio\impl\write.hpp(46): error C2228: left of '.write_some' must have class/struct/union 
1>   type is 'boost::asio::basic_stream_socket<Protocol> ' 
1>   with 
1>   [ 
1>    Protocol=boost::asio::ip::tcp 
1>   ] 
1>   did you intend to use '->' instead? 
1>   c:\boost\boost_1_47\boost\asio\impl\write.hpp(59) : see reference to function template instantiation 'size_t boost::asio::write<SyncWriteStream,ConstBufferSequence,boost::asio::detail::transfer_all_t>(SyncWriteStream &,const ConstBufferSequence &,CompletionCondition,boost::system::error_code &)' being compiled 
1>   with 
1>   [ 
1>    SyncWriteStream=boost::asio::ip::tcp::socket *, 
1>    ConstBufferSequence=boost::asio::mutable_buffers_1, 
1>    CompletionCondition=boost::asio::detail::transfer_all_t 
1>   ] 
1>   c:\users\josh\documents\visual studio 2010\projects\client\client\main.cpp(53) : see reference to function template instantiation 'size_t boost::asio::write<boost::asio::ip::tcp::socket*,boost::asio::mutable_buffers_ 1>(SyncWriteStream &,const ConstBufferSequence &)' being compiled 
1>   with 
1>   [ 
1>    SyncWriteStream=boost::asio::ip::tcp::socket *, 
1>    ConstBufferSequence=boost::asio::mutable_buffers_1 
1>   ] 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

Come si può vedere, i punti il ​​messaggio di errore direttamente in un file di Boost write.hpp, e non a qualsiasi di mio codice .. Credo che sto chiamando write() in modo non corretto, ma dopo un'intensa ora di ricerca su google e ricerca di riferimenti ed esempi (che utilizzano un altro sovraccarico write() o si utilizzano dati con dimensioni/strutture specificatamente definite), non sono stato in grado di determinare cosa esattamente io sto sbagliando qui

Qualcuno può aiutarmi a eseguire il debug di questo errore di compilazione?

risposta

14

documentazione sembra mancare

Il highest voted question in è sulla documentazione, cominciare da lì :-)

Qualcuno può aiutarmi a eseguire il debug di questo errore di compilazione?

write() La funzione libera expects un tipo di riferimento come primo parametro. Non è un puntatore come hai nel tuo esempio

bool sendMessage(tcp::socket* sock, uint16_t opcode, void* data) 
{ 
    void* fullData = malloc(sizeof(uint16_t) + sizeof(data)); 
    memcpy(fullData, (void*)opcode, sizeof(opcode)); 
    memcpy(&fullData + sizeof(uint16_t), data, sizeof(data)); 
    boost::asio::write(*sock, boost::asio::buffer(fullData, sizeof(fullData))); 
    //     ^^^^ correct type now 
    // by the way, at this point, is it safe to delete fullData to prevent memory leaks? 
    return true; 
} 

a questo punto, è sicuro di eliminare fullData per evitare perdite di memoria?

Sì, write() is una chiamata di blocco. È fatto con il tuo buffer quando la chiamata ritorna. Suggerisco caldamente di rendere questo codice eccezionalmente sicuro, tuttavia osservate l'uso di new e di boost::scoped_array se volete creare il vostro buffer con durata di archiviazione dinamica.

+0

Ha funzionato alla grande, grazie! :) E ho visto la "più alta domanda votata" molte volte nel mio google, e ho seguito il suo consiglio, ma non con molto successo ... gli esempi hanno usato diverse versioni sovraccaricate di write(), il riferimento di classe basato su molti boost flussi con cui non ho familiarità, ecc. – Josh1billion