如何通过QTCPSocket发送文件及其文件名?

5

有没有一种简单的方法可以将包含文件名的文件发送到服务器,以便服务器和客户端中的文件名完全相同?

这是我的代码

发送者

QString path = QApplication::applicationDirPath()+"/belajardansa.bmp";
QFile inputFile(path);
QByteArray read ;
inputFile.open(QIODevice::ReadOnly);
while(1)
{
    read.clear();
    read = inputFile.read(32768*8);
    qDebug() << "Read : " << read.size();
    if(read.size()==0)
       break;
    qDebug() << "Written : " << socket->write(read);
    socket->waitForBytesWritten();
    read.clear();
}
inputFile.close();

接收器

QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
QBuffer* buffer = buffers.value(socket);

QByteArray read = socket->read(socket->bytesAvailable());
qDebug() << "Read : " << read.size();

QFile file(  ???); // what should I put in the bracket???
if(!(file.open(QIODevice::Append)))
{
    qDebug("File cannot be opened.");
    exit(0);
}
file.write(read);
file.close();
2个回答

6
  1. 您可以创建自己的数据结构来表示文件内容及其文件名,并将其转换为QByteArray,反之亦然。

  2. 您可以发送两个请求:第一个请求包含文件名,第二个请求包含数据。


感谢您的回复,汉克。 您的第一个建议对我来说有点复杂,因为我是C++和Qt的新手。您能否给我提供一个将数据结构转换为QByteArray的示例代码?至于您的第二个建议,如何将套接字数据转换,以便服务器可以识别套接字数据是否包含文件名或数据。 - Ananta S.

6
没有真正简单的方法。您必须创建自己的协议。但是,该协议通常可以非常简单。
在编写端,以下是一个简单的示例:
  1. 使用QString::toUtf8()将QString文件名转换为QByteArray
  2. 将QByteArray的长度作为二进制整数写入套接字
  3. 将包含文件名的QByteArray的字节写入套接字
  4. 将文件的长度作为二进制整数写入套接字
  5. 将文件的字节写入套接字
  6. 关闭
在读取端:
  1. 读取告诉文件名长度的整数
  2. 读取与文件名长度相同的字节数到QByteArray中
  3. 使用QString::fromUtf8()将文件名从QByteArray转换为QString
  4. 读取告诉数据长度的整数
  5. 继续读取字节并将其写入文件,直到读取的字节数等于数据长度
  6. 关闭
当写入和读取时,如果要在不同计算机之间通信,则应在写入之前将其转换为网络字节序,并在读取后恢复主机字节序。您还可以决定定义使用“ x86字节排序”,并且任何使用不同CPU读取数据的人都需要进行转换...

谢谢您的回复,海德。 您的建议似乎非常有用。但对于像我这样的新手来说,有一个问题。 如何处理传入的套接字数据,以便我可以将数据放到该协议中的正确步骤中。(我们知道,在TCP中,写入的数据会被分成一些数据包发送。) - Ananta S.
TCP/IP是一种流协议,您可以编写和读取字节,而不是数据包。它还保证了所有字节的顺序和传输。因此,您可以信任您将按照完全相同的顺序获得完全相同的字节(否则会出现错误和断开连接)。这也是为什么您必须向套接字编写自己的“数据包大小”的原因,因为TCP/IP不会给您带有大小的数据包,只提供字节流。 - hyde
还有一个澄清:当然,你可以一次写入和读取多个字节的数据,这是从你写入和读取时使用的方法中可以看出来的。只是你写入的大小会丢失,接收方不知道你是先写了10个字节再写了100个字节,还是一次性写入了110个字节。 - hyde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接