2013-07-15 129 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

相关问题