【问题标题】:How can I improve upload / download speeds over socket server application?如何通过套接字服务器应用程序提高上传/下载速度?
【发布时间】:2021-02-11 21:38:22
【问题描述】:

我正在尝试将一个大文件从我的计算机上传到不同网络中的另一台计算机。但是,文件传输速度非常慢。是什么导致我的代码出现瓶颈?

以下代码供上传者使用:

public static void main(String [] args) throws IOException {
    /*
     * Take a file, read it into a byte array using the File Input Stream
     * Then send that byte array using a Buffered Output Stream
     * Done
     */
    ServerSocket serverSocket = new ServerSocket(port);
    Socket clientSocket = serverSocket.accept();
    BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
    
    File file = new File(fileToSend);
    FileInputStream fis = new FileInputStream(file);
    byte[] byteArray = fis.readAllBytes();
    bos.write(byteArray);
    bos.flush();
    bos.close();
}

这是我用来下载文件的内容:

public static void main(String[] args) throws UnknownHostException, IOException {
    /*
     * Open up a socket, then get the byte array using a buffered input stream
     * then use a file output stream to write out the file
     */
    long start = System.currentTimeMillis();
    Socket socket = new Socket(hostName, port);
    BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
    byte[] byteArray = bis.readAllBytes();
    FileOutputStream fos = new FileOutputStream(fileOutput);
    fos.write(byteArray);
    long end = System.currentTimeMillis();
    System.out.println("Download time: " + (end - start)/1000);
}

慢,我的意思是通过这个程序上传一个 100MB 的文件大约需要 6-7 分钟,而在谷歌驱动器上上传几乎不需要一分钟。我还在努力学习套接字服务器编程,所以请告诉我瓶颈在哪里。

【问题讨论】:

  • google 服务器的网络路径与您的网络路径不同,这可能会导致部分或全部速度差异。您可以使用Files 类中的copy() 方法来简化并可能加快传输速度。

标签: java sockets stream network-programming


【解决方案1】:

您正在通过以下方式一次读取 RAM 中的所有字节:

byte[] byteArray = fis.readAllBytes();

然后你将所有字节写入你的套接字:

bos.write(byteArray);

因此,您必须等到所有 100 MB 从文件系统加载完毕,然后再等到这些字节发送完毕。而在下载器中,您可以反过来执行此操作。

您可以通过将这两个作业拆分为单独的线程来减少此时间。

  • 第一个线程不断地从您的 FS 读取 n 个字节(如 1024)并将其存储在共享的同步列表中。
  • 第二个线程正在读取列表中的 n 个字节并将其写入客户端。

这些线程也可以通过 PipedInputStream 和 PipedOutputStream 相互通信: https://docs.oracle.com/javase/7/docs/api/java/io/PipedInputStream.html https://docs.oracle.com/javase/7/docs/api/java/io/PipedOutputStream.html

此外,您还可以使用 GZIP 之类的压缩流: https://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPOutputStream.html https://docs.oracle.com/javase/7/docs/api/java/util/zip/GZIPInputStream.html.

你应该考虑使用 A(utomatic)R(esource)M(management)-Blogs https://www.oracle.com/technical-resources/articles/java/trywithresources.html

【讨论】:

    猜你喜欢
    • 2016-06-28
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多