2011-10-27 54 views
3

我寫了一個小程序,用於將文件從一個客戶端發送到另一個客戶端。我已經爲接收者和客戶端設置了進度條,但問題是發件人的進度條完成速度比實際傳輸快得多。問題在於它如何計算已寫入的字節數。我假設它正在計算我讀入緩衝區的字節數,而不是通過網絡發送的字節數,所以我如何才能找到解決此問題的解決方案?接收方正在以正確的速率計算他接收的字節數,但發送方沒有正確地執行他的部分。測量通過Java套接字寫入的實際字節數

設置一個較低的緩衝區大小抵消了一點差異,但它仍然不正確。我試着用CountingOutputStream包裝輸出流,但它返回的結果與下面的代碼片段相同。傳輸最終會正確完成,但我需要正確的「發送」值來更新我的進度條,就像在接收端實際接收和寫入光盤的內容一樣。我已經包含了一個非常精簡的代碼片段,它代表了我計算傳輸字節的方式。任何解決方案的例子都會很有幫助。

try 
    { 
    int sent = 0; 
    Socket sk = new Socket(ip, port); 
    OutputStream output = sk.getOutputStream(); 
    FileInputStream file = new FileInputStream(filepath); 

    byte[] buffer = new byte[8092]; 

    while ((bytesRead = file.read(buffer)) > 0) 
     { 
     output.write(buffer, 0, bytesRead); 
     sent += bytesRead; 
     System.out.println(sent); // Shows incorrect values for the actual speed. 
     } 
    } 
+0

您可以在輸出之後立即嘗試調用輸出流上的flush() .write()調用,這將刷新緩衝區並實際上導致數據通過網絡發送。但是,緩衝區可以提高性能,並且如果保持flush()性能可能會受到影響。 – prunge

+0

@prunge flush()不會*'實際上導致數據在網絡上傳輸',實際上flush()在未裝飾的套接字輸出流上什麼也不做。 – EJP

+0

@EJP你是對的,看着源代碼顯示flush()什麼也不做。我想有些事情要做,以減少延遲可能是套接字setTcpNoDelay(false),這將關閉[Nagel的算法](http://en.wikipedia.org/wiki/Nagle%27s_algorithm)。 – prunge

回答

2

從套接字獲取輸入流,另一方面,當您向磁盤寫入字節選擇時,將結果寫入輸出流。產生第二個線程來處理這些信息的讀取,並將其鏈接到您的櫃檯。

您的變量是sent - 它是準確的。你需要的是一個receivedprocessed變量,爲此你需要雙向通信。

4

簡而言之,考慮到您和「wire」本身之間的緩衝區數量,我認爲您完全可以從「發件人」一方獲得您要查找的準確可見度。但是,我認爲這不重要。原因如下:

  1. 當它們被交給網絡堆棧時,字節計數爲「已發送」。當你發送少量字節(比如你的8K例子)時,這些字節將被緩衝& write()調用將很快返回。

  2. 一旦您達到網絡飽和,您的write()調用將會隨着各種網絡緩衝區變滿而開始阻塞 - 因此您將會對時序有一個真正的瞭解。

  3. 如果你真的必須有某種「你收到多少字節?」您必須讓接收端通過帶外機制(例如glowcoder建議)定期發回數據。