4

PC 間で大きなファイル (少なくとも 16 GB) を送受信しようとしています。クライアント アプリケーションが約 2GB を受信すると、アプリケーションがフリーズし、ほとんどすべてのメモリが消費されます (約 2GB のメモリも消費されます)。サーバーサイドではこの問題はありません。

ファイルを送信するサーバーコードは次のとおりです

clock_t startTime = clock();
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),
            clientConnection, SLOT(deleteLater()));

QString sourceFileName("/path/to/source/sourcefile.big");
QByteArray baFName=sourceFileName.toLocal8Bit();
char* c_fileName=baFName.data();

char buf[BUFSIZ];
size_t size;
unsigned long long sendSize=0;
int source = open64(c_fileName, O_RDONLY, 0);
unsigned long long loopCount=0;
while ((size = read(source, buf, BUFSIZ)) > 0) {
    sendSize=clientConnection->write(buf, size);
    clientConnection->waitForBytesWritten();
    if(sendSize< size) {
       qWarning("transmit error!");
    }
    qDebug() << "Loop #" << ++loopCount << " send data: " << sendSize;

}

qDebug() << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds.";

clientConnection->disconnectFromHost();

アプリケーションのクライアント側は、受け取ったファイルの大きさをすでに知っています。ファイルを受け取ってディスクに書き込むコードは次のとおりです。

clock_t startTime = clock();

QString sourceFileName("/path/to/target/targetfile.big");
unsigned long long targetSize=16447314864ULL;

unsigned long long loopCount=(targetSize / 8192ULL) + ( targetSize % 8192ULL > 0 ? 1 : 0);
QByteArray baFName=sourceFileName.toLocal8Bit();
char* c_fileName=baFName.data();

char buf[BUFSIZ];
size_t size;
unsigned long long sendSize=0;
int dest = open64(c_fileName, O_WRONLY | O_CREAT, 0644);

while (loopCount){
    if (tcpSocket->waitForReadyRead()){
        size=tcpSocket->read(buf, 8192);
        write(dest, buf, size);
        qDebug() << "Loop #" << loopCount << " receive data: " << size;
        loopCount--;
    }
}

qDebug() << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds.";

問題があれば、ubuntu 14.04を使用しています。

4

3 に答える 3

2

loopCount を取り除くことから始めるべきです。受信したバイト数と受信するバイト数を比較します。

tcpSocket->bytesAvailable() も利用したいと思うでしょう。

このコードを試してみてください: 一般的なアイデアが得られるかもしれません。

unsigned long long totalBytesRead = 0;
while (totalBytesRead < targetSize) {
    if (tcpSocket->waitForReadyRead()) {
            unsigned long long bytesAvailable = tcpSocket->bytesAvailable();
            char buf[bytesAvailable];
            totalBytesRead += bytesAvailable;
            write(dest, buf, size);
            qDebug() << "Loop #" << loopCount << " receive data: " << size;
    }
}

また、QT コードを作成しているので、QFile を使用することもできます。また、これを使用する手間も省けます。

char* c_fileName=baFName.data();

代わりにこれを持つことができるので

QFile file("/path/to/target/targetfile.big");
于 2014-05-27T01:03:51.743 に答える
0

クライアント側のフリーズとメモリの占有の問題を解決することができました。waitForReadyRead() が原因であることが判明しました。

それを削除して、tcpSocket->read の出力を確認するだけです。ゼロの場合は、数ミリ秒の遅延を入れて、今度はプロセッサを占有しないようにします。

waitForByteWritten() を削除すると、サーバー側が高速になるのではないかと思います。clientConnection->bytesToWrite() をチェックして 1GB に制限しようとしましたが、数値が下がらないことがわかりました。waitForByteWritten() を同期的に置き換えるために使用できる他の方法はありますか?

于 2014-05-27T09:33:08.023 に答える