2

送金の受け取りに問題があります。

QTcpSocket-> readAll()は、送信時に十分なバイトを読み取りません。15kバイトを送信すると、その一部のみが読み取られ、何も実行されません。私は何が間違っているのですか?

QByteArray array;

array = socket->readAll(); //just reads some part, not fully.

なぜこれが起こるのですか?

4

1 に答える 1

10

を呼び出したときに、ソケットがまだすべてのデータを受信して​​いない可能性がありますreadAll()。これは、TCP通信が小さなパケットで発生するためです(多くの場合、それぞれに約1KBのデータがあります)。これらのパケットは、通信回線のもう一方の端がバイトを書き込むストリームを構成します。受信側で組み立てる必要があります。それらをどのように組み立てるかは、プロトコルで定義する必要があります。

この問題を解決するには、予想されるすべてのデータを待ってから組み立てる必要があります。(プロトコルによっては)読み取らない限り、予想されるデータ量がわからない場合があります。

「改行までのすべてがメッセージと呼ばれるものである」というプロトコルを実装するとします。今、あなたはそのようなメッセージを受け取りたいです。QByteArrayこれは、改行が発生するまでターゲットバッファ(のような)を連続して読み取り、追加することによって行われます。ただし、別のことがあります。2番目のメッセージを予期する場合、TCPストリームの最初のメッセージの直後になる可能性があるため、最初のメッセージの終わりだけでなく、2番目のメッセージの始まりも読み取るだけです。これを覚えておいてください。

信号スロット接続を処理しない場合は、次のような改行で区切られたメッセージの同期レシーバーを作成できます。

QByteArray array;

while(!array.contains('\n')) {
    socket->waitForReadyRead();
    array += socket->readAll();
}

int bytes = array.indexOf('\n') + 1;     // Find the end of message
QByteArray message = array.left(bytes);  // Cut the message
array = array.mid(bytes);                // Keep the data read too early

processMessage(message);

を扱うときQTcpSocket::readyRead()、あなたは同じようなことをすることができます。

void MyClass::socketReadyRead() // connected to QTcpSocket::readyRead() signal
{
    array += socket->readAll();

    if(array.contains('\n')) {
        int bytes = array.indexOf('\n') + 1;     // Find the end of message
        QByteArray message = array.left(bytes);  // Cut the message
        array = array.mid(bytes);                // Keep the data read too early

        processMessage(message);

        socketReadyRead();                       // re-call myself to process more
    }
}

1つのTCP接続を介して送信されたすべてを(ピアによって閉じられるまで)読み取りたい場合は、このイベントをブロックする方法で待機するか、適切な信号に接続されたスロットでデータを処理できますQTcpSocket::disconnected

ブロッキング:

socket->waitForDisconnected();
QByteArray array = socket->readAll();

ノンブロッキング(スロットを使用した信号の処理):

void MyClass::socketReadyRead() // connected to QTcpSocket::readyRead() signal
{
    array += socket->readAll();
    // Do NOT process yet!
}

void MyClass::socketDisconnected() // connected to QTcpSocket::disconnected() signal
{
    processMessage(array);
}

代替のノンブロッキングソリューション(基本的に同じ):

// You don't have to connect to QTcpSocket::readyRead() signal in this case

void MyClass::socketDisconnected()
{
    processMessage(socket->readAll());
}
于 2013-01-07T02:23:31.600 に答える