Qt通过TCP发送文件

Wil*_*Dev 2 qt tcp file

我在单个应用程序中执行 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

......我猜这是正确的

服务器(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();
    }
}
Run Code Online (Sandbox Code Playgroud)

......这是问题:while第一次迭代后坏了。

看:

ToSend 50000 
ToSend 50000 
ToSend 50000 
ToSend 31135 
Total: 181135 
Received 50000 
Run Code Online (Sandbox Code Playgroud)

如您所见,只收到了 1 个区块而不是 4 个。

如何解决这个问题?为什么bytesAvailable不应该返回 0?知道这种通过 tcp 接收文件的好方法是否也很好:)

Seb*_*nge 5

可能是因为只有这一包可用。在发送数据之前,您需要就文件大小进行协商。然后等待所有数据传输完毕。处理完前 50k 数据后,BytesAvailable() 将返回 false。如果您再次调用 bytesAvailable() 等待 1 秒,您可能会得到另一个数据包。

在发送数据之前实现一个 4 字节的“大小数据包”并检查正在接收的那些字节。

所以你的协议将是:

  • 大小包
  • 数据包
  • n次数据包

另一种选择是使用预定义的结束数据包,但如果您的文件可以在原始数据中包含此数据包,则这可能很危险。如果您可以确保您的数据不包含您的最终数据包,您最终将实现该协议:

  • 数据包
  • n次数据包
  • 结束包