1

クライアントが構造体データをサーバーに送信するときに問題が発生します。クライアントは Qt tcp を使用し、サーバーは boost.asio を使用します。サーバー側では、クライアントから送信されたバッファ データを受信できますが、データを構造体データにキャストすると、構造体データが読み取れなくなります。

これは問題の構造体データです:

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

これは、クライアント ソケットでデータを読み取るためのサーバー内のコードです。

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

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

これは、構造体データを送信するクライアントのコードです。

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

1 に答える 1

2

QDataStream operator <<シリアル化に使用され、生データをそのまま書き込むのではありません。
たとえば、バイト シーケンスは32-bits、シーケンスのサイズを示す「ヘッダー」と共に送信されます。

また、構造全体を にキャストしているためchar*、それを文字列として解釈し、構造体の一部にある最初の'\0'文字で停止します。int

したがって、2 つのメンバーを別々に記述し、明示的なキャストを避ける必要があります。

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

ブースト asio 側では、構造体のサイズがわかっているため、構造体全体が受信される前に後者が返される可能性があるため、async_read代わりに使用する必要があります。async_read_some

于 2011-11-29T14:03:25.993 に答える