3

我想使用 Qt UDP(不是 TCP)套接字来传输文件。所以我写这样的代码:

发件人

QFile file1(QString::fromStdString(filedir));
QByteArray bytes;
file1.open(QIODevice::ReadOnly);
QTextStream in(&file1);
while (!in.atEnd()) {
    bytes = in.read(8192).toAscii();
    udpSocket.writeDatagram(bytes, QHostAddress(ip), port.toInt());
}

接收者

udpSocket1.bind(ui->sendPort->text().toInt());
connect(&udpSocket1,SIGNAL(readyRead()),this,SLOT(listenfile()));

void Widget::listenfile() {
    QFile file("received.txt");
    file.resize(0);
    file.open(QIODevice::Append);
    QTextStream out(&file);
    do {
        QByteArray data;
        data.resize(udpSocket1.pendingDatagramSize());
        udpSocket1.readDatagram(data.data(),data.size());
        QString str=data.data();
        ui->textBrowser1->append(str);
        out << data;
    } while (udpSocket1.hasPendingDatagrams());
}

当我发送小文件时,没有问题。但是,如果我想发送大文件(> 8192 字节),即使在 localhost 上测试,接收方也只能获得前 8KB 的数据。如果我减少发送方的大小数字,例如 1024。接收方仍然只能获得前 8KB 的数据。如果我将发送方的大小数增加到 X 字节(X > 8192)。接收方将获得前 X 字节数据。

似乎要传输的 Qt UDP 数据包的最小大小是 8192 字节。接收者总是得到第一个数据包,但不能接收其他数据包。

我对Qt和网络编程经验很少,所以不知道我的猜想是否正确。你能告诉我如何更改这些代码以支持在第一个数据包之后接收数据包,以便我可以传输大数据吗?

4

2 回答 2

4

调试了半天,用Wireshark抓包。我认为问题的原因是 QUdpSocket 本身。像 Internet 上的许多其他示例一样,我的代码可能是正确的。但是 QUdpSocket 类不适合传输大数据。因为连接到readyRead()的slot函数在执行时,后续的数据报不能再次触发,直到函数执行完毕。所以发送方必须在发送一些数据后休眠一段时间以等待接收方的 slot 函数。

结论是 QUdpSocket 类是不可靠的传输大数据。我应该使用底层的Socket API,定制一些协议,设计多进程/多线程架构,从根本上解决问题。当然,使用 TCP 套接字是另一种选择。

于 2013-03-28T12:41:57.483 回答
3

您的问题可能来自这一行:

} while (udpSocket1.hasPendingDatagrams());

您期望整个数据包集排队并准备好立即接收,但更有可能的是一些数据包将可用,稍后会有更多数据包可用。因此,您需要比这更长的时间监听套接字并确定对方何时真正完成发送数据。

于 2013-03-18T12:58:23.190 回答