Domanda

ho un problema quando il mio cliente invia i dati struct al mio server. Il mio client utilizza Qt TCP ei miei usi di server boost.asio. Sul mio lato server, posso ricevere i dati di buffer inviati dal client, ma quando io scaccio i dati per i miei dati struct, ottengo un dato struct illeggibili.

Questi sono i dati struct in questione:

struct Protocole
{
  int type;
  char infos[1024];
}

Questo è il codice nel mio server di leggere i dati sul client socket:

    this->_socket.async_read_some(boost::asio::buffer(_buffer), // _buffer is type of char[1024];
    _strand.wrap(boost::bind(&ClientManager::HandleRead, 
    this, 
    boost::asio::placeholders::error, 
    boost::asio::placeholders::bytes_transferred))
    );

nel ClientManager :: HandleRead:

ProtocoleCS *_proto; // this is the struct data i have to cast 

_proto = static_cast<ProtocoleCS*>(static_cast<void*>(&_buffer));
// I can read _proto

Questo è il codice nel mio client per inviare i dati struct:

void                Network::SendMsgToServer()
{   
    QByteArray      block;
    QDataStream     out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_7);
    Protocole       proto;

    proto.type = 1;

    std::cout << " i am sending a message" << std::endl;

    proto._infos[0] = 'H';
    proto._infos[1] = 'E';
    proto._infos[2] = 'L';
    proto._infos[3] = 'L';
    proto._infos[4] = 'O';
    proto._id[5] = '\0';

    out <<  static_cast<char*>(static_cast<void*>(&proto));
    this->socket->write(block);
}
È stato utile?

Soluzione

QDataStream operator << viene utilizzato per la serializzazione, e non scrivere dati grezzi come è.
Ad esempio sequenze di byte vengono inviati con un 32-bits "header" che indica la dimensione della sequenza.

E perché si sta lanciando l'intera struttura per char*, si interpreta come una stringa e si ferma al primo carattere '\0', che si trova nella parte int della struct.

Per questo si deve invece scrivere i due membri separatamente ed evitare cast esplicito:

// If you want to avoid endianness swapping on boost asio side
// and if both the server and the client use the same endianness
out.setByteOrder(QDataStream::ByteOrder(QSysInfo::ByteOrder));

out << proto.type; 
out.writeRawData(proto.infos, sizeof(proto.infos));   

Su spinta asio parte, dal momento che si conosce la dimensione della struct, si dovrebbe usare async_read invece di async_read_some perché il ritorno potrebbe quest'ultimo prima che l'intera struttura è stata ricevuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top