1

初めて、HostileForkが私の問題を説明するのを手伝ってくれたことに感謝したいと思います。ありがとうございます !

バイナリプロトコルを介してデータを送信するクライアントとサーバーを構築しようとしています。

私の問題は、QTクライアントからBoostサーバーにクラスを送信したいということです。私のヘッダー(私のクラスのサイズである1つの整数)がソケットに書き込んでいます。サーバー側でヘッダーを読み取りたい場合、適切な整数を取得できません(代わりに、-13050660のような大きな数値があります)。サーバーでのデシリアライズに問題があると思いますが、よくわかりません。

これは、私のQtクライアントコードが番号10をソケットに書き込むために使用する手法です。

QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint32) 0;
out.device()->seek(0);
out << (quint32) (10);
cout << "Writing " << sizeof(quint32) << " bytes to socket." << endl;

次に、boostのasync_read()を使用するサーバープロセスでそれを読み取ろうとします。

this->Iheader.resize(size, '\0'); // Iheader is a vector of char
async_read(
    this->socket,
    buffer(this->Iheader),
    bind(
        &Client::endRead,
        cli,
        placeholders::error,
        placeholders::bytes_transferred)
);

文字列の結果を操作する関数は次のとおりです。

#ifdef WIN32
    #define MYINT INT32
    #include <Windows.h>
#else
    #define MYINT int
#endif

void Client::endRead(const error_code& error, size_t nbytes)
{
    if (!error && nbytes == sizeof(MYINT)) {
        cout << "Read " << sizeof(MYINT) << " bytes from a socket." << endl;
        istringstream stream(this->connection->getIheader(nbytes));
        stream >> this->Isize;
        cout << "Integer value read was " << this->Isize << endl;
    } else {
        cout << "Could not read " << sizeof(MYINT) << " bytes." << endl;
    }
}

32ビットの符号付き整数(4バイト)を取得しますが、10ではなく、-1163005939のようなものです。誰かが持っていて、なぜこれが機能しないのか考えていますか?

サーバーとクライアントはどちらも、64ビットのWindows7proで起動しています。

4

2 に答える 2

1

どういたしまして...そして、質問の編集に関する私の提案に従い、問題をより明確に特定するために必要な努力をしてくれてありがとう。だから今、私はあなたに何が悪いのかを言うことができます。:)

との動作は、C++標準IOストリーム<<>>は異なります。QDataStreamこれらの演算子のようなクラスの世界では、「インstd::stringstreamサーター」/「エクストラクター」と呼ばれ、テキストとしてフォーマットされた情報を処理することを目的としています。特定のバイト数をメモリアドレスに読み込みたい場合は、次のようにします。

http://www.cplusplus.com/reference/iostream/istream/read/

(文字列ストリームではないものからバイナリデータを読み取りたい場合は、ios :: binaryを使用して、行末変換を台無しにしないようにする必要があることに注意してください)

QDataStreamその規則に従わない...それはバイナリデータの良いヘルパーです。それは何も悪いことではありません...抽象的に言えば、<<and>>演算子は言語で利用可能であり、独自のクラス階層内でやりたいことを実行するためにオーバーロードすることができます。Qtは、独自のストリームに対して独自のセマンティクスを自由に定義できました。

入力と出力の両方に同じ方法を使用することについて(可能であれば)@vitakotからのアドバイスに注意してください。また、注意しないと発生し始めるバイト順序の問題についての私の警告にも注意してください。

(良いニュースは、それを使用している場合は、あなたのためにそれを世話することQDataStreamによってこの問題を解決することです。)

記述されたコードでは、文字列ストリームがバッファから読み取るためにバッファのコピーを作成していることに注意してください。私はboost::asioの経験やベストプラクティスはasync_readありませんが、掘り下げて見つけることができるより良い方法があると確信しています。

于 2011-11-21T21:56:47.373 に答える
0

HostileForkは正しいです。私たちが持っている情報から、コードのバグを特定することはできません。

ただし、Qtクライアントでもブーストシリアル化を使用することをお勧めします。BoostライブラリとQtライブラリを組み合わせない理由はありません。そうしないと、ネットワークを介してより複雑なクラスを送信するときに多くの問題に対処する必要があります...

于 2011-11-21T22:13:59.973 に答える