3

Qt UDP (TCP ではなく) ソケットを使用してファイルを転送したいと考えています。だから私は次のようなコードを書きます:

送信者

QFile file1(QString::fromStdString(filedir));
QByteArray bytes;
file1.open(QIODevice::ReadOnly);
QTextStream in(&file1);
while (!in.atEnd()) {
    bytes = in.read(8192).toAscii();
    udpSocket.writeDatagram(bytes, QHostAddress(ip), port.toInt());
}

レシーバー

udpSocket1.bind(ui->sendPort->text().toInt());
connect(&udpSocket1,SIGNAL(readyRead()),this,SLOT(listenfile()));

void Widget::listenfile() {
    QFile file("received.txt");
    file.resize(0);
    file.open(QIODevice::Append);
    QTextStream out(&file);
    do {
        QByteArray data;
        data.resize(udpSocket1.pendingDatagramSize());
        udpSocket1.readDatagram(data.data(),data.size());
        QString str=data.data();
        ui->textBrowser1->append(str);
        out << data;
    } while (udpSocket1.hasPendingDatagrams());
}

小さなファイルを送る場合は問題ありません。ただし、大きなファイル (> 8192 バイト) を送信したい場合、ローカルホストでテストしても、受信側は上位 8KB のデータしか取得できません。1024 など、送信側のサイズ数を減らすと、受信側は依然として上位 8KB のデータしか取得しません。送信者のサイズ番号を X バイト (X > 8192) に増やした場合。レシーバーは、上位 X バイトのデータを取得します。

転送する Qt UDP パケットの最小サイズは 8192 バイトのようです。受信者は常に最初のパケットを取得しますが、他のパケットを受信することはできません。

私は Qt とネットワーク プログラミングの経験がほとんどないため、私の推測が正しいかどうかわかりません。大きなデータを転送できるように、これらのコードを変更して最初のパケットの後にパケットを受信できるようにする方法を教えてください。

4

2 に答える 2

4

長い間デバッグし、Wireshark を使用してパケットをキャプチャした後。問題の原因は QUdpSocket 自体にあると思います。インターネット上の他の多くの例と同様に、私のコードはおそらく正しいでしょう。ただし、QUdpSocket クラスは大きなデータの転送には適していません。readyRead() に接続されたスロット関数が実行中の場合、後続のデータグラムは関数が完了するまでスロット関数を再びトリガーできないためです。そのため、送信側はデータを送信した後、受信側のスロット関数を待機するためにしばらくスリープする必要があります。

結論として、QUdpSocket クラスは大きなデータを転送するのに信頼できるものではありません。問題を根本的に解決するには、低レベルのソケット API を使用し、いくつかのプロトコルをカスタマイズし、マルチプロセス/マルチスレッド アーキテクチャを設計する必要があります。もちろん、TCP ソケットを使用することも別の選択肢です。

于 2013-03-28T12:41:57.483 に答える
3

あなたの問題はおそらくこの行から来ています:

} while (udpSocket1.hasPendingDatagrams());

パケットのセット全体がキューに入れられ、一度に受信できるようになることを期待していますが、一部が利用可能になり、後でさらに多くのパケットが利用可能になる可能性が高くなります。したがって、それより長くソケットをリッスンし、相手側が実際にデータの送信を終了したのはいつかを判断する必要があります。

于 2013-03-18T12:58:23.190 に答える