QTcpServer "überlastet" mit zu großen Dateien

Alles rund um die Programmierung mit Qt
Antworten
jw202
Beiträge: 36
Registriert: 6. August 2012 22:25

QTcpServer "überlastet" mit zu großen Dateien

Beitrag von jw202 »

Hallo,

ich versuche ein Programm für den FileTransfer zu basteln.


Folgender Code-Teil sendet eine Datei (befindet sich in der run()-Methode eines Threads):

Code: Alles auswählen

    QTcpSocket socket;
    socket.connectToHost(host,port);
    socket.waitForConnected();

    QFile f(file);
    f.open(QIODevice::ReadWrite);

    qint64 size = f.size();
    qint64 current = 0;
    qint64 read;
    char data[65536];
    while (!f.atEnd() && socket.state() == QTcpSocket::ConnectedState)
    {
        read = f.read(data,65536);
        socket.write(data,read);
        socket.flush();
        socket.waitForBytesWritten();
        current += read;
        emit progress(current,size);
    }
    f.close();

Die Datei wird von einem QTcpServer empfangen (ohne Threads). Im Prinzip habe ich das Signal newConnection() mit einer Methode verbunden, welche eine Datei QFile f; bereitstellt und den dazugehörigen Socket mit dem Signal ReadyRead() verknüpft, sodass bei eingehenden Bytes folgende Methode aufgerufen wird:

Code: Alles auswählen

void recvServer::onRead()
{
    QByteArray data = conn->read(qMin(this->bytesLeft, (quint64)65536));
    f.write(data);
    f.flush();
    this->bytesLeft -= data.length();
    if (this->bytesLeft == 0)
    {
        f.close();
        fin = true;
        conn->disconnectFromHost();
        emit finished();
    }
    emit progress(size-bytesLeft,size);
}

Fazit: kleine Dateien werden korrekt übertragen. Große Dateien (1.8 GB) werden manchmal unvollständig übertragen, der Abbruch erfolgt nicht-deterministisch aber meistens irgendwo zwischen 30 und 40 MB (mit Ausnahmen). Die beiden Dateien stimmen bis zur Bruchstelle bitweise überein. Den Debugmeldungen und dem Fortschrittsbalken ist zu entnehmen, dass die Datei von Clientseite vollständig gesendet wird. Beim Server kommt hingegen nur die unvollständige Datei an. Außerdem geht der Fortschrittsbalken beim Senden viel schneller als beim Empfangen. Und der GUI hängt beim Empfänger.

Meine Vermutung: Das mit dem ReadyRead-Signal ist dem Empfänger zu aufwendig und er liest zu langsam. Ich habe die Befürchtung, dass ich den Empfänger in ein Thread verpacken muss (was ich aber nicht wirklich will -.-)


LG und danke schon im Voraus



Nachtrag: ich teste die gesamte Konstruktion auf einem einzigen Rechner mit der Loopback-Adresse unter Ubuntu Linux. Außerdem ist ein QTcpServer für nur eine Datei bestimmt. Es gibt also nicht das Problem, dass auf einen Server mehrfach zugegriffen werden könnte.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QTcpServer "überlastet" mit zu großen Dateien

Beitrag von Christian81 »

Ich hab eigentlich keine Probleme beim Übertragen von großen Dateien. Ist evtl. die Platte zu langsam? Das QFile::flush() erzeugt einen Sync der m.E. unnötig ist. Auch das QSocket::flush() ist nicht m.E. nötig. Ich übertrage meist 1MB oder mehr anstatt nur die 65k.. waitForBytesWritten() hat auch noch einen Rückgabewert den Du mal prüfen könntest. Was sagt Wireshark dazu?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
odt
Beiträge: 128
Registriert: 12. August 2010 11:49
Kontaktdaten:

Re: QTcpServer "überlastet" mit zu großen Dateien

Beitrag von odt »

clientseitig ein assert( current == file.size ) nach der schlaufe
wird server.bytesLeft richtig initialisiert? wie?
kommt er in server.finish?
serverseitig readAll verwenden (theoretisch könnte der In-Buffer > blocksize sein und dann wird onRead nicht mehr aufgerufen obwohl noch Daten...)
wenn's denn mal läuft und wenn client nicht-blockierend sein soll, nicht threading sondern das senden in einem slot verknüpft mit socket->bytesWritten
ODT Informatik GmbH, Reto Tschofenig
odt
Beiträge: 128
Registriert: 12. August 2010 11:49
Kontaktdaten:

Re: QTcpServer "überlastet" mit zu großen Dateien

Beitrag von odt »

rückgabewert von socket.write überprüfen
ODT Informatik GmbH, Reto Tschofenig
jw202
Beiträge: 36
Registriert: 6. August 2012 22:25

Re: QTcpServer "überlastet" mit zu großen Dateien

Beitrag von jw202 »

Problem gelöst, es lag daran, dass in der Server-Funktion onRead() nicht alles gelesen wurde, weil die Funktion anscheinend nicht oft genug aufgerufen wurde. Ich hätte stattdessen readAll() verwenden sollen, oder eine while-Schleife außen herum stellen, die überprüft, ob noch was zum Lesen übrig ist.


vielen Dank für die Hilfe :) :)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QTcpServer "überlastet" mit zu großen Dateien

Beitrag von Christian81 »

Oh, das habe ich übersehen - ja das ist natürlich korrekt. Man muss entweder readAll() benutzen oder so lange lesen wie bytesAvailable() true ist.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten