如何通过套接字发送非常大的对象

时间:2012-12-12 16:45:43

标签: java sockets large-data

我的系统涉及通过TCP套接字发送大量数据和元数据。我发送一个包含各种元数据的对象,以及20个字节的数组。到目前为止,我一直在使用包含BufferedOutputStream的ObjectOutputStream来处理小例子(130kB数组)。我尝试达到67MB阵列的目标,但ObjectOutputStream无法处理那么多数据。我能够发送1MB数组,但writeObject()挂起2MB。

我听说DataOutputStream更快,但我宁愿不必将元数据编码为字节并在另一端解码。是否有一个很好的替代方案可以快速发送非常大的对象?

修改

我在每个write方法后都使用了reset()。我目前正在发送一个SignedObject,它包含我自己的Message对象,该对象包含20个数组以及许多元数据字段。我更喜欢把它全部打包,因为它非常方便,但我知道分离可能是唯一的方法。话虽这么说,我仍然需要确保所有传输都是安全的。

更新

所以我去吃午饭,回来了,并决定我试着弄清楚发送或接收端是否挂起了东西。然后它永远不会挂断。我可以继续成功发送最多4MB阵列,直到我用完堆(这是无关的,只是意味着我需要一台更好的计算机或更高效的处理)。所以我猜问题就消失了?并不意味着我不需要更好的传播方式,所以如果人们拥有它们,我会采取更多的想法。另外,我假设我一更新一次,就会再次停止工作......

1 个答案:

答案 0 :(得分:1)

  

是否有一个很好的选择,能够快速发送非常大的物体?

在发送的对象之间使用ObjectOutputStream和reset()。除非你只有几MB的内存(其中你应该得到更多)你不会有问题。

与自己编码字节相比,ObjectOutputStream相当慢,但它可以很好地处理编码。网络上传速度更可能是您的限制因素。在这个例子中,它发送大约600 Mb / s,而大多数braodband连接大约500 kb / s(大约慢1000倍)

ServerSocket ss = new ServerSocket(0);
Socket s = new Socket("localhost", ss.getLocalPort());
final Socket s2 = ss.accept();
ss.close();

new Thread(new Runnable() {
    @Override
    public void run() {
        int count = 0;
        long start = System.nanoTime();
        try {
            ObjectInputStream in = new ObjectInputStream(
                    new InflaterInputStream(s2.getInputStream()));
            while (in.readObject() != null) count++;
            s2.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        long time = System.nanoTime() - start;
        System.out.printf("Read %,d objects in %.3f seconds%n", count, time / 1e9);
    }
}, "reader").start();
ObjectOutputStream oos = new ObjectOutputStream(
        new DeflaterOutputStream(s.getOutputStream()));
for (int i = 0; i < 20; i++) {
    byte[] bytes = new byte[67 * 1000 * 1000];
    oos.writeObject(bytes);
    oos.reset();
}
oos.writeObject(null); // poison pill
oos.close();
s.close();

打印

Read 20 objects in 21.644 seconds