InputStream 没有收到 EOF

Posted

技术标签:

【中文标题】InputStream 没有收到 EOF【英文标题】:InputStream not receiving EOF 【发布时间】:2011-11-29 04:37:43 【问题描述】:

我正在尝试通过套接字将图像从我的 android 设备发送到我的计算机。问题是我计算机上的输入流读取每个字节,但最后一组。我已经尝试修剪字节数组并发送它,我已经多次手动将-1写入输出流,但输入流从不读取-1。它只是挂起等待数据。我也尝试过不关闭流或套接字以查看是否是某种时间问题,但效果不佳。

客户端(Android 手机)

//This has to be an objectoutput stream because I write objects to it first
InputStream is = An image's input stream android
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(object);
objectOutputStream.flush();

byte[] b = new byte[socket.getSendBufferSize()];
int read = 0;
while ((read = is.read(b)) != -1) 
   objectOutputStream.write(b, 0, read);
   objectOutputStream.flush();
   b = new byte[socket.getSendBufferSize()];

//Tried manually writing -1 and flushing here
objectOutputStream.close();
is.close();
socket.close();

服务器端(计算机) 这段代码发生在对象输入流读入发送的对象之后。只有在文件开始发送时才开始读取

File loc = Location of where the file is stored on the computer
loc.createNewFile();
FileOutputStream os = new FileOutputStream(loc);
Socket gSocket = The socket
ObjectInputStream gInputStream = Object Input stream created from the sockets input stream already used to read in the previous objects

byte[] b = new byte[gSocket.getReceiveBufferSize()];
int read = 0;
while ((read = gInputStream.read(b)) != -1) 
   os.write(b, 0, read);
   os.flush();
   b = new byte[gSocket.getReceiveBufferSize()];


os.close();

即使我直接写入 -1 并刷新流,此代码也不会读入 -1。结果是 java.net.SocketException: Connection reset when the stream or socket from the android device is closed。图片几乎完全发送,但图片的最后一个像素是灰色的。我什至还尝试直接从套接字使用输出/输入流,而不是使用已经创建的 objectinputstream/objectoutputstream,但它仍然不起作用。

【问题讨论】:

有一点值得注意,您只需创建一次byte[]。使用 read(b) 意味着您正在从偏移量 0 开始读取数组,并返回读取的字节数。后续调用只会覆盖任何先前的数据。 我实际上将数组重新初始化为套接字当前支持的大小。所以我不需要偏移量。 套接字当前支持的大小不会改变,除非你改变了它,而且无论如何为你的应用程序缓冲区使用相同的大小并没有什么特别的优势。 【参考方案1】:

首先,我认为您误解了 EOF (-1) 的含义。这并不意味着服务器写了一个-1,这意味着服务器关闭了流。

我认为您的主要问题是服务器和客户端都在循环读取,并且都没有到达关闭流的地步。它们陷入僵局 - 两者都在等待另一个先关闭。

您的客户:

您的服务器:

如果您知道没有更多数据要写入,那么只需关闭流。

【讨论】:

客户端的流完全结束并关闭流。那是服务器收到 EOF 异常的时候。 @user695992:您发布的代码显示客户端在关闭自己的流之前等待服务器关闭其流。 等待关闭的流是图像输入流。所以客户端每次从图像输入流中读取一组字节,并将其推送到输出流中。服务器一次从客户端读取一组字节,然后推送到文件的输出流。【参考方案2】:

由于您已经在使用ObjectInputStreamObjectOutputStream,您可以使用它们各自的readObjectwriteObject 方法一次读取/写入整个对象。也许您可以将整个字节数组作为对象发送/接收?

在你的安卓上:

1) 字节[] imageBytes = ...; // 包含图片

2) objectOutputStream.writeObject(imageBytes);

在您的计算机上:

1) byte[] imageBytes = (byte[])readObject();

2) 从 imageBytes 获取图像

当然,您必须在线程中使用readObject,因为它会阻塞。

【讨论】:

是的。这会阻塞,但不幸的是我不能使用它,因为文件会导致内存不足错误。完整对象的问题是您必须先将整个对象读入内存。不过感谢您的回复。【参考方案3】:

您正在将 byte[] 数组作为对象编写,而不是读取字节。您应该阅读 Objects 并将它们转换为 byte[]。 EOS 将导致抛出 EOFException。

【讨论】:

以上是关于InputStream 没有收到 EOF的主要内容,如果未能解决你的问题,请参考以下文章

将大型 JSON (InputStream) 放入 String 时出现内存不足错误

如何使用 UTF-8 读取 InputStream?

InputStream 在 spring 控制器中关闭

为啥 InputStream 没有完全填充数组?

记录由输入量决定的时间[重复]

有没有办法使用 Guava 获取 InputStream 的哈希码?