2014-06-10 114 views
1

我在單個應用程序內部執行TCP文件客戶端服務器。Qt通過TCP發送文件

主要是,我發送每50000字節的文件名和文件的和。

客戶:

void client::sendFile(QString path) 
{ 
    QDataStream out(cl); 
    QFile toSend(path); 

    if (toSend.open(QIODevice::ReadOnly)) 
    { 
     int s = 0; 

     QFileInfo fileInfo(toSend.fileName()); 
     QString fileName(fileInfo.fileName()); 
     out << fileName; 

     while (!toSend.atEnd()) 
     { 
      QByteArray rawFile; 
      rawFile = toSend.read(50000); 
      out << rawFile; 
      qDebug() << "ToSend"<<rawFile.size(); 
      s+=rawFile.size(); 
     } 

     qDebug() << "Total:" << s; 
    } 
} 

...這是正確的我猜

服務器(ReadyRead插槽):

void server::receive() 
{ 
    QTcpSocket *sender = (QTcpSocket*) this->sender(); 

    QDataStream in(sender); 

    QString fName; 
    in >> fName; 
    QFile newFile("D:\\"+fName); 

    if (newFile.open(QIODevice::WriteOnly)) 
    { 
     while(sender->bytesAvailable()) 
     { 
      QByteArray z; 
      in >> z; 
      newFile.write(z); 
      qDebug() << "Received " << z.size(); 
     } 

     newFile.close(); 
    } 
} 

...這是問題:第一itteration後while破。

看:

ToSend 50000 
ToSend 50000 
ToSend 50000 
ToSend 31135 
Total: 181135 
Received 50000 

正如你看到的,只接受,而不是4

1塊如何解決這一問題?爲什麼bytesAvailable在不應該時返回0? 會很好,知道這是很好的方法來接收文件通過TCP或不是:)以及:)

+1

我想在你的接收器中,你必須等到181135字節收到。 – vahancho

回答

3

可能是因爲只有這一個數據包可用。在發送數據之前,您需要設置關於文件大小的協商。然後等待所有數據傳輸。 BytesAvailable()在處理完第一個50k數據後立即返回false。如果再次調用bytesAvailable()等待1秒鐘,則可能會得到另一個包。

在發送數據並檢查接收到的字節之前,先執行一個4字節的「大小數據包」。

所以你protocoll將是:

  • 數據包大小
  • 數據包
  • n次的數據包

另一種選擇是有一個預定義的終端數據包,但如果您的文件可以包含原始數據中的數據包,這可能會很危險。

  • 數據包
  • n次的數據包
  • 結束分組
2

你:如果你能保證你的數據不包含您的最終包你作爲最終將落實協議「發明」一種協議,讓接收者知道將傳輸多少數據。 bytesAvailable只顯示到目前爲止收到的字節數,可以從流中讀取哪些字節數,但是它不知道將來發送方仍將傳輸多少數據。

請參閱here瞭解如何做到這一點的一個非常簡單的例子。

1

問題是你在等待bytesAvailable()的循環。

readyRead插槽旨在處理此問題。當您的插槽被調用時,請閱讀可用字節數並處理它們。你應該從函數返回。

當有更多數據可用時,您將在readyRead插槽功能中再次調用。

當然,這意味着您將需要在連續調用之間緩衝數據,並且建議通過發送服務器期望整個文件的字節數的頭來啓動該過程。一旦服務器累積了這個字節數,它就可以寫出新文件。