Qt通过TCP发送文件

时间:2014-06-10 10:37:13

标签: qt file tcp

我在单个应用程序中执行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接收文件的好方法:)

3 个答案:

答案 0 :(得分:4)

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

实施4字节&#34;大小数据包&#34;在发送数据并检查接收的字节之前。

所以你的协议将是:

  • 尺寸包
  • 数据包
  • n次数据包

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

  • 数据包
  • n次数据包
  • End Packet

答案 1 :(得分:2)

您必须“发明”一种协议,允许接收方知道将传输多少数据。 bytesAvailable仅显示到目前为止收到的字节数,可以从流中读取,但它不知道发件人将来还会传输多少数据。

有关如何执行此操作的简单示例,请参阅here

答案 2 :(得分:1)

问题是你的循环等待bytesAvailable()。

readyRead插槽用于处理此问题。调用插槽时,读取可用的字节数并处理它们。然后你应该从函数返回。

当有更多数据可用时,您将在readyRead插槽功能中再次调用。

当然,这意味着您需要在连续调用之间缓冲数据,建议通过发送服务器对整个文件期望的字节数的标头来启动该过程。一旦服务器累积了该字节数,它就可以写出新文件。