QT Client Envía un struct Data para aumentar el servidor ASIO
-
25-10-2019 - |
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);
}
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.