如何使用Qt UDP套接字发送和接收大数据?

时间:2013-03-18 12:06:44

标签: qt sockets network-programming udp

我想使用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和网络编程方面经验不足,所以我不知道我的猜想是否正确。你能告诉我如何更改这些代码以支持在第一个数据包之后接收数据包,以便我可以传输大数据吗?

2 个答案:

答案 0 :(得分:4)

调试很长时间后使用Wireshark捕获数据包。我认为问题的原因是QUdpSocket本身。像互联网上的许多其他例子一样,我的代码可能是正确的。但是QUdpSocket类不适合传输大数据。因为当连接到readyRead()的槽函数正在执行时,后续数据报在函数完成之前不能再次触发它。因此发送方必须在发送一些数据后等待接收方的插槽功能一段时间。

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

答案 1 :(得分:3)

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

} while (udpSocket1.hasPendingDatagrams());

您期望整个数据包排队等待,并且可以立即接收,但更有可能是某些数据包可用,之后会更多。所以你需要比那个更长时间监听套接字,并确定对方实际上何时完成发送数据。