2012-09-03 60 views
5

我在写一个需要通过网络发送文件的应用程序。到目前为止,我只被教过如何使用标准的java.net和java.io类(在大学的第一年),所以我没有使用java.nio和netty以及所有这些好东西。我有一个工作的服务器/客户端设置采用Socket和ServerSocket类用BufferedInput/OutputStreams和BufferedFile流一起,如下:如何正确缓冲我的Java输入/输出/文件流?

服务器:

public class FiletestServer { 

    static ServerSocket server; 
    static BufferedInputStream in; 
    static BufferedOutputStream out; 

    public static void main(String[] args) throws Exception { 
    server = new ServerSocket(12354); 
    System.out.println("Waiting for client..."); 
    Socket s = server.accept(); 
    in = new BufferedInputStream(s.getInputStream(), 8192); 
    out = new BufferedOutputStream(s.getOutputStream(), 8192); 
    File f = new File("test.avi"); 
    BufferedInputStream fin = new BufferedInputStream(new FileInputStream(f), 8192); 

    System.out.println("Sending to client..."); 
    byte[] b = new byte[8192]; 
    while (fin.read(b) != -1) { 
     out.write(b); 
    } 
    fin.close(); 
    out.close(); 
    in.close(); 
    s.close(); 
    server.close(); 
    System.out.println("done!"); 
    } 
} 

而且客户端:

public class FiletestClient { 

    public static void main(String[] args) throws Exception { 
    System.out.println("Connecting to server..."); 
    Socket s; 
    if (args.length < 1) { 
     s = new Socket("", 12354); 
    } else { 
     s = new Socket(args[0], 12354); 
    } 
    System.out.println("Connected."); 
    BufferedInputStream in = new BufferedInputStream(s.getInputStream(), 8192); 
    BufferedOutputStream out = new BufferedOutputStream(s.getOutputStream(), 8192); 
    File f = new File("test.avi"); 
    System.out.println("Receiving..."); 
    FileOutputStream fout = new FileOutputStream(f); 
    byte[] b = new byte[8192]; 
    while (in.read(b) != -1) { 
     fout.write(b); 
    } 
    fout.close(); 
    in.close(); 
    out.close(); 
    s.close(); 
    System.out.println("Done!"); 
    } 
} 

起初我不使用缓冲,和写入每一从in.read INT()。根据我在Windows 7上的网络监视器小工具,我得到了大约200kb/s的传输量。然后,我如上所述对其进行了更改,但使用了4096字节的缓冲区并获得了相同的速度,但收到的文件通常比源文件大几千字节,这就是我的问题所在。我将缓冲区大小更改为8192,现在我通过无线方式将大约3.7-4.5mb/sec的数据传输到我的笔记本电脑上,现在速度足够快,但我仍然遇到文件稍微变大的问题(这会导致它当它被接收时,通过md5/sha哈希测试)。

所以我的问题是什么是缓冲获得体面的速度和准确地与在另一侧相同的文件结束的正确方法?让它快一点也不错,但我现在对速度感到满意。我假设一个更大的缓冲区更好一点,我只需要找出那个点是什么。

回答

5

被您忽略的数据的大小实际读取。

while (in.read(b) != -1) { 
    fout.write(b); 
} 

将总是写8192个字节,即使只有一个字节被读取。相反,我建议使用

for(int len; ((len = in.read(b)) > 0;) 
    fout.write(b, 0, len); 

你的缓冲区大小为您的byte []所以他们是不是真的这样做,此刻什么一样。

的MTU对于大多数网络是在1500字节,你会得到较慢网络上的性能改进(高达1 GB)高达2 KB。 8 KB也很好。比这更大的帮助不大可能。

+0

啊,打我给它。 – martijno

+0

@martijno我需要放慢脚步。 ;) –

+0

我明白忽略导致问题的数据大小部分,但我不明白for循环。它看起来像是以某种方式读取,只从缓冲区写入数据直到实际内容结束 - 这是否正确?编辑:你有一个太多的括号,“((LEN = ...”应为“(LEN = ...” – Logan