2013-03-18 100 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