Question

I have an issue when my client sends struct data to my server. My client uses Qt tcp and my server uses boost.asio. On my server side, I can receive the buffer data sent by the client, but when I cast the data to my struct data, I get a struct data unreadable.

This is the struct data in question :

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

this is the code in my server to read data on the 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))
    );

in the 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

This is the code in my Client to send the struct data :

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);
}
Was it helpful?

Solution

QDataStream operator << is used for serialization, and not to write raw data as is.
For example byte sequences are sent with a 32-bits "header" indicating the size of the sequence.

And because you are casting the whole structure to char*, it interprets it as a string and stops at the first '\0' character which is in the int part of the struct.

So you should rather write the two members separately and avoid explicit casting:

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

On boost asio side, since you know the size of the struct, you should use async_read instead of async_read_some because the latter might return before the whole structure has been received.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top