Pregunta

Tengo un problema cuando mi cliente envía datos de estructura a mi servidor. Mi cliente usa QT TCP y mi servidor usa Boost.asio. En el lado de mi servidor, puedo recibir los datos del búfer enviados por el cliente, pero cuando lanzar los datos a mis datos de estructura, obtengo un struct data injustable.

Estos son los datos de estructura en cuestión:

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

Este es el código en mi servidor para leer datos en el socket del cliente:

    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))
    );

En el 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

Este es el código de mi cliente para enviar los datos de 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);
}
¿Fue útil?

Solución

QDataStream operator << se usa para la serialización y no para escribir datos sin procesar como está.
Por ejemplo, las secuencias de byte se envían con un 32-bits "Encabezado" que indica el tamaño de la secuencia.

Y porque estás lanzando toda la estructura a char*, lo interpreta como una cadena y se detiene en el primero '\0' personaje que está en el int parte de la estructura.

Por lo tanto, debe escribir a los dos miembros por separado y evitar el casting explícito:

// 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));   

En el lado de Boost ASIO, ya que conoce el tamaño de la estructura, debe usar async_read en vez de async_read_some Porque este último podría regresar antes de que se haya recibido toda la estructura.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top