我正在尝试从PC向另一台PC发送和接收一些大文件(至少16GB)。 当客户端应用程序收到大约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。
答案 0 :(得分:1)
你应该从摆脱loopCount开始。将接收的字节数与要接收的字节数进行比较。
您还需要使用tcpSocket-&gt; 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");
答案 1 :(得分:1)
最好的方法是通过将套接字的readyRead()信号连接到插槽来以异步模式接收数据:
connect( tcpSocket, SIGNAL(readyRead()),
this, SLOT(tcpReady()) );
来自Qt文档:
每次有新数据时,都会发出一次该信号 从设备上读取。只有新数据才会再次发出 可用,例如当新的网络数据有效载荷到达时 在您的网络套接字上,或附加了新的数据块 到你的设备。
您可以读取连接到readyRead信号的插槽中的数据:
void MyClass::tcpReady()
{
unsigned long long bytesAvailable = tcpSocket->bytesAvailable();
char buf[bytesAvailable];
totalBytesRead += bytesAvailable;
write(dest, buf, size);
qDebug() << "Loop #" << loopCount << " receive data: " << size;
}
答案 2 :(得分:0)
我设法解决了客户端的冻结和内存占用问题。 事实证明,waitForReadyRead()是它的原因。
我只是删除它并检查tcpSocket-&gt;读取的输出。如果它为零,那么我会延迟几毫秒,这样它就不会成为处理器生猪了。
我想知道如果删除waitForByteWritten(),服务器端是否会更快。我试图检查clientConnection-&gt; bytesToWrite()并将其限制为1GB,但事实证明这个数字不会下降。有没有其他方法可以用来同步替换waitForByteWritten()?