我在单个应用程序中执行TCP文件客户端 - 服务器。
首先,我每50000字节发送文件名和文件的和平。
客户端:
void client::sendFile(QString path)
{
QDataStream out(cl);
QFile toSend(path);
if (toSend.open(QIODevice::ReadOnly))
{
int s = 0;
QFileInfo fileInfo(toSend.fileName());
QString fileName(fileInfo.fileName());
out << fileName;
while (!toSend.atEnd())
{
QByteArray rawFile;
rawFile = toSend.read(50000);
out << rawFile;
qDebug() << "ToSend"<<rawFile.size();
s+=rawFile.size();
}
qDebug() << "Total:" << s;
}
}
......这是正确的我猜
服务器(ReadyRead插槽):
void server::receive()
{
QTcpSocket *sender = (QTcpSocket*) this->sender();
QDataStream in(sender);
QString fName;
in >> fName;
QFile newFile("D:\\"+fName);
if (newFile.open(QIODevice::WriteOnly))
{
while(sender->bytesAvailable())
{
QByteArray z;
in >> z;
newFile.write(z);
qDebug () << "Received " << z.size();
}
newFile.close();
}
}
......以及问题:while
在第一次尝试后被打破。
看:
ToSend 50000
ToSend 50000
ToSend 50000
ToSend 31135
Total: 181135
Received 50000
如您所见,只收到1个区块而不是4区。
如何解决这个问题?为什么bytesAvailable
在不应该返回0时为什么会返回0?
很高兴知道这是通过tcp接收文件的好方法:)
答案 0 :(得分:4)
可能是因为只有这一个数据包可用。您需要在发送数据之前建立有关文件大小的协商。然后等待所有数据传输。一旦处理完第一个50k数据,BytesAvailable()就返回false。如果再次调用bytesAvailable()等待1秒钟,你可能会得到另一个数据包。
实施4字节&#34;大小数据包&#34;在发送数据并检查接收的字节之前。
所以你的协议将是:
另一个选择是拥有一个预定义的结束数据包,但如果您的文件可以在原始数据中包含此数据包,这可能会很危险。如果您可以确保您的数据不包含您的最终数据包,您最终将实现协议:
答案 1 :(得分:2)
您必须“发明”一种协议,允许接收方知道将传输多少数据。 bytesAvailable
仅显示到目前为止收到的字节数,可以从流中读取,但它不知道发件人将来还会传输多少数据。
有关如何执行此操作的简单示例,请参阅here。
答案 2 :(得分:1)
问题是你的循环等待bytesAvailable()。
readyRead插槽用于处理此问题。调用插槽时,读取可用的字节数并处理它们。然后你应该从函数返回。
当有更多数据可用时,您将在readyRead插槽功能中再次调用。
当然,这意味着您需要在连续调用之间缓冲数据,建议通过发送服务器对整个文件期望的字节数的标头来启动该过程。一旦服务器累积了该字节数,它就可以写出新文件。