2013-07-15 188 views
0

最近,我編寫了一個簡單的客戶端服務器程序,用於通過標準TCP套接字進行文件傳輸。 WiFi通道的平均吞吐量約爲2.2Mbps。我的問題是: 是否可以通過多個數據IO流傳輸大文件(比如5 GB),以便每個流可以以並行方式傳輸同一文件的多個部分(不同的線程可用於此目的)?這些文件部分可以在接收端重新組裝。 我試圖拆分一個小文件並通過數據輸出流傳輸它。第一部分工作正常,但我不知道如何以選擇性的方式讀取文件輸入流(我也嘗試使用mark()和reset()方法進行選擇性讀取,但沒有用處)通過使用多個IO流的java套接字進行文件傳輸

這是我的代碼用於測試目的,我重定向輸出到FileOutputStream中):

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    final File myFile=new File("/home/evinish/Documents/Android/testPicture.jpg"); 
    long N=myFile.length(); 
    try { 
     FileInputStream in=new FileInputStream(myFile); 
     FileOutputStream f0=new FileOutputStream("/home/evinish/Documents/Android/File1.jpg"); 
     FileOutputStream f1=new FileOutputStream("/home/evinish/Documents/Android/File2.jpg"); 
     FileOutputStream f2=new FileOutputStream("/home/evinish/Documents/Android/File3.jpg"); 

     byte[] buffer=new byte[4096]; 
     int i=1, noofbytes; 
     long acc=0; 
     while(acc<=(N/3)) { 
      noofbytes=in.read(buffer, 0, 4096); 
      f0.write(buffer, 0, noofbytes); 
      acc=i*noofbytes; 
      i++; 
     } 
     f0.close(); 

我得到了我的文件的第一部分(這可以在一個線程中被複制到一個DataOutputStream類)。任何人都可以建議,如何在一段N/3中讀取文件的剩餘部分(在N/3字節之後),以便三個線程可以在三個線程中用於併發操作?

這是在接收器端合併文件段代碼:

package com.mergefilespackage; 
import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.Closeable; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

public class MergeFiles { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) throws Exception{ 
     // TODO Auto-generated method stub 
     IOCopier.joinFiles(new File("/home/evinish/Documents/Android/File1.jpg"), new File[] { 
      new File("/home/evinish/Documents/Android/File2.jpg"), new File("/home/evinish/Documents/Android/File3.jpg")}); 
    } 
} 
class IOCopier { 
    public static void joinFiles(File destination, File[] sources) 
      throws IOException { 
     OutputStream output = null; 
     try { 
      output = createAppendableStream(destination); 
      for (File source : sources) { 
       appendFile(output, source); 
      } 
     } finally { 
      IOUtils.closeQuietly(output); 
     } 
    } 

    private static BufferedOutputStream createAppendableStream(File destination) 
      throws FileNotFoundException { 
     return new BufferedOutputStream(new FileOutputStream(destination, true)); 
    } 

    private static void appendFile(OutputStream output, File source) 
      throws IOException { 
     InputStream input = null; 
     try { 
      input = new BufferedInputStream(new FileInputStream(source)); 
      IOUtils.copy(input, output); 
     } finally { 
      IOUtils.closeQuietly(input); 
     } 
    } 
} 
class IOUtils { 
    private static final int BUFFER_SIZE = 1024 * 4; 

    public static long copy(InputStream input, OutputStream output) 
      throws IOException { 
     byte[] buffer = new byte[BUFFER_SIZE]; 
     long count = 0; 
     int n = 0; 
     while (-1 != (n = input.read(buffer))) { 
      output.write(buffer, 0, n); 
      count += n; 
     } 
     return count; 
    } 

    public static void closeQuietly(Closeable output) { 
     try { 
      if (output != null) { 
       output.close(); 
      } 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 
} 

任何幫助,將不勝感激!提前致謝!

+1

如果你想通過同一個WiFi通道輸出更多的數據,它可能會變慢,因爲每個套接字都會增加其他的爭用。 – hexafraction

+0

+1 to @hexafraction。問題是限制因素是什麼。我懷疑(像@hex),你正在被無線網速限制,並且因爲其他連接將在同一個無線信道上,所以它們將不能並行工作。 – Gray

+0

@Gray作爲答案發布。 – hexafraction

回答

3

對於更多套接字的鏈接,您無法獲得更多速度。每個套接字發送一定數量的數據包,每個數據包都有一定的大小。隨着套接字數量加倍,數據包數/秒*套接字減半,然後由於衝突,開銷和爭用而減少了甚至更​​多。數據包開始碰撞,混亂和恐慌。操作系統無法處理丟失ACK的混亂情況,並且WiFi卡正在努力以這樣的速度進行傳輸。它也在失去低級哎呀。隨着數據包丟失,絕望的TCP協議棧會降低傳輸速率。如果由於信號改善而出現這種情況,由於愚蠢的窗口綜合症或另一種形式的TCP死鎖,它現在停滯在較低的速度。

即使只有一個插座,任何嘗試通過WiFi獲得更高速度的更寬的載波頻段,MiMo或多路徑,已經實現爲增益。你不能再走得更遠。

現在,等待。我們低於WiFi速度,不是嗎?當然,我們需要使用緩衝!

確保從套接字的getInputStream或getOutputStream方法創建BufferedWriter和BufferedReader對象。然後寫入/讀取這些緩衝區。你的速度可能會有所增加。

+0

+1由於WIFI信道吞吐量的限制,每個套接字的吞吐量減半。 – Gray

0

你可以得到FileInputStream的字節數組並且每10KB分隔一次(每10.000字節)。 然後按順序通過流發送這些部分。

在服務器上,您可以再次將數組放在一起,並從這個巨大的字節數組中讀取文件。

+1

10KB **!= ** 10000bytes – BackSlash

+0

這不會導致更高的吞吐量,更復雜的代碼 – Gray

+0

那麼......然後分割它每隔10240個字節 – MinecraftShamrock

相關問題