【问题标题】:Send file bytes inside object through socket通过套接字在对象内部发送文件字节
【发布时间】:2014-09-29 17:58:10
【问题描述】:

我已经尝试了几天,但没有成功。

我想通过套接字客户端/服务器发送文件。唯一的区别是:我想发送一个包含文件字节的对象。

所以客户端加载一个文件,读取1024字节的块,将它们存储在一个对象中,然后将对象发送到服务器。由于文件可能大于 1024 字节,我想重复发送对象,但在其中存储不同的字节(当缓冲区读取它时)。在服务器上,我想组合字节数组并将其保存为文件。

我使用 1024 的原因是因为我想避免任何类型的内存不足错误,如果文件大小为 4 GB。

我尝试在客户端上执行以下操作:

File file = new File("C:\\test\\test.txt");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
byte[] bytes = new byte[1024];

FileTest ft = new FileTest();
ft.setName("Testing");
int counttest = 1;

while (bis.read(bytes) > 0) {
    ft.setCounttest(counttest);
    ft.setBytes(bytes);
    oos.writeObject(ft);
    counttest += 1;
}

在服务器上:

int bufferSize = socket.getReceiveBufferSize();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\test\\test2.txt"));    
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
byte[] bytes = new byte[bufferSize];

while (true) {
    FileTest ft = (FileTest) ois.readObject();
    if (ft != null) {
        System.out.println(ft.getName());
        bos.write(ft.getBytes());
    }
}

所以我测试了发送一个带有数字序列的 txt 文件,而服务器生成的 test2.txt 文件只输出了前 1024 个字节块重复了两次。此外,counttest 整数在服务器中接收时永远不会增加。

知道如何做到这一点吗?

提前致谢。

【问题讨论】:

  • 你的对象实现可序列化了吗? docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
  • 永远不要丢弃bis.read(bytes) 实际读取的字节数,因为它很可能通过套接字读取的字节数少于完整字节数。
  • 如果一次读取大块字节,则不需要缓冲流。

标签: java sockets tcp


【解决方案1】:

您遇到了 ObjectOutputStream 尝试保留对象身份的影响。重复写入相同的对象实例将导致接收者端的 same 实例。这通常是一件好事,但如果您在发送者端修改对象并期望这些修改会在接收者端出现,则会令人困惑。

因此,您有两个问题:

  1. 为了每次都发送数据,您要么需要每次都创建一个新的 FileTest 实例,要么使用writeUnshared() 方法。
  2. 由于这种身份保留行为,您需要定期reset() ObjectOutputStream 以防止所有这些实例被永久保留(并可能导致客户端或服务器上出现 OOME)。

【讨论】:

  • +1 您可以使用.reset().writeUnshared(ft); 来避免这种情况,但是我会完全避免使用ObjectOutputStream。我会使用更高效但更简单的 DataOutputStream。
  • 实例化一个新的 FileTest 对象有效。但是,输出文件的前 1024 个字节仍然重复了两次(原始文件为 2K)。知道如何解决这个问题吗?
  • @rodd - 除其他外,您需要考虑read() 方法返回的值。
  • bos.write(ft.getBytes(), 0, ft.getCount());没用,能否请您解释一下如何完成此操作?
  • 我刚刚检查过,服务器正在接收与以前相同的字节,即使客户端正在发送新字节并在循环中实例化一个新对象。如何确保收到不同的字节?
猜你喜欢
  • 2012-08-29
  • 2012-03-13
  • 2019-04-21
  • 2014-01-11
  • 2022-01-15
  • 2021-01-11
  • 2011-02-24
相关资源
最近更新 更多