【问题标题】:Sending a large file over TCP channel with serialization通过带有序列化的 TCP 通道发送大文件
【发布时间】:2012-03-17 19:24:15
【问题描述】:

我正在用 Java 开发一个客户端-服务器系统。我通过带有序列化对象的 TCP 通道发送消息。

我还需要发送文件。我可以定义自己的自定义消息类:

public class SendFile implements Serializable {
    private byte[] fileContents;

    ...
}

然后发送。如果我们有一个大文件,这会带来一个问题,据我了解,它会在将文件发送到另一端之前尝试将所有内容都保存在内存中。

我已经阅读了有关Externalizable 的信息,但如果在通过 TCP 通道发送文件之前仍在将文件读取到我的所有计算机内存中,那也不会更好。我想要一些“懒惰”的方式来做到这一点(当我通过网络发送它时从磁盘读取它,并从内存中丢弃已经读取的内容)。

处理这个问题的最简洁的方法是什么?在最坏的情况下,我可以把它分成小块,但如果可能的话我想避免它。

编辑:

当然,我可以在文件上打开一个流并“发送”。但这意味着以不同的方式处理发送文件和所有其他消息,这是我希望避免的。

谢谢

【问题讨论】:

  • 难道你不能只拥有一个大小可调的预读缓存,以便在磁盘访问中只保留几个步骤的数据包头部吗?
  • 我不确定我是否理解你的意思。当我们有一个可序列化的对象时,整个对象在发送到另一端之前都会被序列化,对吧?
  • 是的,如果你自动序列化它。但如果你自己做......为什么这是你的“最坏情况”?

标签: java oop serialization externalizable


【解决方案1】:

绕过它的一种方法是使用流媒体。流式处理方法不会将全部内容加载到内存中。您可以打开两个流,来自要通过网络发送的对象的 input-stream 和用于 TCP 套接字连接的 output-stream

在 java 中,InputStreamOutputStream。支持字节的读写。

您可以定义缓冲区大小(字节数组)。使用 InputStream.read(byte[] b) 将内容读取(从文件)到该缓冲区,并使用 OutputStream.write(byte[] b) 将相同的缓冲区写入(到 TCP 套接字)到输出流

【讨论】:

  • 这是显而易见的答案。但这意味着以不同的方式处理此消息或其他类型的消息,这是我希望避免的。
  • 为什么不直接将它们全部流式传输......您正在堆栈上编写基于自定义低级套接字的应用程序,不是吗?也许原始的 TCP rfc 会有用 op.to/42Kb/plain/text/ietf+
【解决方案2】:

您可以直接在缓冲区中读取 Java 文件并通过网络发送该缓冲区,而不是使用 Java 序列化。为什么在 b/w 中涉及 java 序列化和复杂的东西。使用简单的 n/w 程序,您将能够发送文件。

【讨论】:

    猜你喜欢
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2015-07-14
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    相关资源
    最近更新 更多