2013-03-18 99 views
2

我想使用Qt UDP(不是TCP)套接字来传输文件。 所以我写这样的代码:如何使用Qt UDP套接字发送和接收大数据?

发件人

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字节),接收器只能获得甚至在本地主机上测试的前8KB数据。 如果我减少发件人的大小号码,例如1024.接收者仍然只获得前8KB的数据。 如果我将发件人中的大小编号增加到X个字节(X> 8192)。接收器将获得最高的X字节数据。

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

我在Qt和网络编程方面几乎没有经验,所以我不知道我的猜想是否正确。你能告诉我如何改变这些代码以支持在第一个数据包后接收数据包,这样我就可以传输大数据了吗?

回答

4

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

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

+0

我一直在经历同样的问题一段时间,它真的让我癌症。在用QUdpSocket尝试了许多不同的方法并且花费相当多的时间后,我最终确定了同样的事情:QUdpSocket不适合处理高速率数据流。低级别的winsock udp线程倾向于更好地解决问题。但确实,**真的很难过。我希望Qt提出解决这个严重问题的方案。 – 2017-07-19 14:14:31

2

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

} while (udpSocket1.hasPendingDatagrams()); 

你希望整个组数据包的排队,准备在一次被接收,但它更可能是一些将可与以后会更多。因此,您需要监听比此更长的套接字,并确定对方何时实际发送完数据。

+0

谢谢你的回复。你的意思是我应该永远使用另一个线程循环来处理数据报或其他一些简单的方法吗?我认为将readyRead()信号连接到listenfile()插槽可以永久收听套接字。因为当发送者发送第二个文件时,接收者也可以得到顶部数据报而不是忽略。 (也许我错了) – 2013-03-18 14:14:51

+0

正确...只要发射readyRead()信号,您就需要调用您的阅读代码。当一个文件结束而另一个文件开始时,问题将会被检测到。如果需要的话,你可以在数据包前用魔术字节来实现。 IE,总是在数据包前面放置一个值为0x00的1字节数据包,并在数据包前面有一个0x01,因此您知道它是文件的结尾,下一个数据包将会是第二个文件的开始。但是请记住在保存之前删除该字节:-) – 2013-03-19 12:50:30

+0

然而,这并不是首先听起来像是UDP的工作。我不确定为什么你在发送大文件时强制UDP。这就是TCP的意义所在。通常情况下,您应该以1400字节的数据包发送块,以便UDP不需要分片。然后,有这个事实的整个问题,使用UDP你可能会丢失数据包,并不知道它。或者你甚至可以得到一个包两次!想象一下,这会对你传输的文件做些什么!再一次,你应该真的使用TCP。 – 2013-03-19 12:52:33