を使用QTcpSocket
してデータを受信する場合、使用するreadyRead()
信号は で、新しいデータが利用可能であることを示します。ただし、データを読み取るために対応するスロット実装にいる場合、追加は発行されませんreadyRead()
。これは、利用可能なすべてのデータを読み取っている関数に既に入っているため、理にかなっています。
問題の説明
ただし、このスロットの次の実装を想定しています。
void readSocketData()
{
datacounter += socket->readAll().length();
qDebug() << datacounter;
}
readAll()
呼び出し後、スロットを離れる前にデータが到着した場合はどうなりますか? これが他のアプリケーションによって送信された最後のデータ パケット (または、少なくともしばらくの間最後のデータ パケット) である場合はどうなるでしょうか? 追加の信号は発行されないため、すべてのデータを自分で読み取る必要があります。
問題を最小限に抑える 1 つの方法 (ただし、完全に回避するわけではありません)
もちろん、次のようにスロットを変更できます。
void readSocketData()
{
while(socket->bytesAvailable())
datacounter += socket->readAll().length();
qDebug() << datacounter;
}
ただし、問題は解決していません。-checkの直後にデータが到着する可能性は依然としてありますsocket->bytesAvailable()
(関数の絶対的な最後に /another チェックを配置しても、これは解決されません)。
問題を再現できることを確認する
もちろん、この問題はめったに発生しないため、スロットの最初の実装に固執し、人工的なタイムアウトを追加して、問題が確実に発生するようにします。
void readSocketData()
{
datacounter += socket->readAll().length();
qDebug() << datacounter;
// wait, to make sure that some data arrived
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
}
次に、別のアプリケーションに 100,000 バイトのデータを送信させます。これが起こることです:
新しいつながり!
32768 (または 16K または 48K)
メッセージの最初の部分は読み取られますが、再度呼び出されることはないため、最後は読み取られませんreadyRead()
。
私の質問は次のとおりです。この問題が発生しないことを確認する最善の方法は何ですか?
考えられる解決策
私が思いついた解決策の 1 つは、最後に同じスロットを再度呼び出し、スロットの先頭で読み取るデータがあるかどうかを確認することです。
void readSocketData(bool selfCall) // default parameter selfCall=false in .h
{
if (selfCall && !socket->bytesAvailable())
return;
datacounter += socket->readAll().length();
qDebug() << datacounter;
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
QTimer::singleShot(0, this, SLOT(readSocketDataSelfCall()));
}
void readSocketDataSelfCall()
{
readSocketData(true);
}
スロットを直接呼び出すのではなく、 を使用するため、スロットを再度呼び出していることを が認識できないQTimer::singleShot()
と想定しているため、発行されない問題はもう発生しません。QTcpSocket
readyRead()
パラメーターを含めた理由bool selfCall
は、によって呼び出されたスロットがQTcpSocket
すぐに終了することが許可されていないためです。そうしないと、同じ問題が再び発生する可能性があり、データが正確に間違ったタイミングで到着し、送信されreadyRead()
ません。
これは本当に私の問題を解決するための最良の解決策ですか? この問題の存在は Qt の設計エラーですか、それとも何か不足していますか?