0

QLocalSocket/QDataStream はどのように読み取ればよいですか?

と を使用して名前付きパイプを介して別のプログラムと通信するプログラムがQLocalSocketありQDataStreamます。下のrecieveMessage()スロットはQLocalSocketreadyRead()信号に接続されています。

void MySceneClient::receiveMessage()
{    
    qint32 msglength;
    (*m_stream) >> msglength;

    char* msgdata = new char[msglength];
    int read = 0;
    while (read < msglength) {
        read += m_stream->readRawData(&msgdata[read], msglength - read);
    }
    ...
} 

アプリケーションがハングアップすることreadRawData()があります。つまり、4 バイトのヘッダーを正常に読み取りますが、readRawData().

付け加えると…

if (m_socket->bytesAvailable() < 5)
    return;

...この関数の開始まで、アプリケーションは正常に動作します (短いテスト メッセージで)。

そのとき、(ドキュメントは非常にまばらです) ある種のデッドロックが発生しており、bytesAvailable()信号を使用して、ブロックするのではなくバッファを徐々に構築する必要があると推測しています。

どうしてこれなの?また、QLocalSocket から読み取る正しい方法は何ですか?

4

1 に答える 1

2

あなたのループはイベントループをブロックするため、すべてが最初に読み取られなかった場合、データを取得することはありません。これが問題の原因だと思います。

正しいアプローチは、シグナルとスロット (readyReadここでは -signal) を使用し、スロットで利用可能なデータを読み取るだけで、十分でない場合はバッファリングして戻り、次のシグナルを取得したときにさらに読み取ることです。

この代替アプローチには注意してください: 期待するすべてのデータがすぐに到着することが絶対に確実な場合 (おそらく、クライアントとサーバーの両方を制御するローカルソケットでは不合理ではない)、またはすべてがスレッド内にある場合他に何もない場合は、waitForReadyReadメソッドを使用しても問題ない場合があります。しかし、イベント ループはデータが到着するまでブロックされたままになり、たとえば (GUI スレッドの場合) GUI がフリーズし、通常は面倒です。

于 2016-12-30T13:54:24.180 に答える