套接字:JPEG 文件过早结束

发布于 2024-11-24 08:51:38 字数 1166 浏览 3 评论 0原文

我正在尝试通过套接字将图像文件从服务器发送到客户端。 套接字以前用于将一些字符串从服务器发送到客户端(使用缓冲的输入/输出流)。

问题是无法正确接收图像文件,出现“JPEG 文件过早结束”错误。

服务器首先将文件大小发送给客户端,然后客户端创建该大小的 byte[],并开始接收文件。

以下是代码:

服务器:

        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        //Send file size
        dos.writeInt((int) file.length());

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        byte[] fileBytes = new byte[bis.available()];
        bis.read(fileBytes);
        bis.close();

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(fileBytes);
        bos.flush();

客户端:

        DataInputStream dis = new DataInputStream(socket.getInputStream());
        //Receive file size
        int size = dis.readInt();

        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] fileBytes = new byte[size];

        bis.read(fileBytes, 0, fileBytes.length);

更有趣的是,如果我让服务器在发送文件大小和写入字节[]之间休眠大约 2 秒,则可以正确接收图像。我想知道服务器和客户端之间是否存在某种竞争条件

I'm trying to send an image file from a server to a client via a socket. The socket was previously used to send some strings from the server to the client (with buffered input/output streams).

The trouble is the image file can't be received properly, with "Premature end of JPEG file" error.

The server first sends the file size to the client, the client then creates a byte[] of that size, and starts to receive the file.

Here are the codes:

Server:

        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        //Send file size
        dos.writeInt((int) file.length());

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        byte[] fileBytes = new byte[bis.available()];
        bis.read(fileBytes);
        bis.close();

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(fileBytes);
        bos.flush();

Client:

        DataInputStream dis = new DataInputStream(socket.getInputStream());
        //Receive file size
        int size = dis.readInt();

        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] fileBytes = new byte[size];

        bis.read(fileBytes, 0, fileBytes.length);

More interestingly, if I let server sleep for about 2 seconds between sending the file size and writing the byte[], then the image is received properly. I wonder if there's some kind of race condition between the server and the client

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

月亮坠入山谷 2024-12-01 08:51:38

错误最有可能出现在此处:

byte[] fileBytes = new byte[bis.available()];

方法 available 不返回文件的大小。它可能只返回输入缓冲区的大小,该大小小于文件的大小。请参阅 BufferedInputStream 中该方法的 API 文档。

另外,下面一行中的 read 不能保证一次性读取整个文件。它返回实际读取的字节数,该数可能小于您要求的字节数。在客户端代码中,您以相同的方式使用read,而无需实际检查它是否读取了所有数据。

The error is most likely here:

byte[] fileBytes = new byte[bis.available()];

The method available does not return the size of the file. It might return only the size of the input buffer, which is smaller than the size of the file. See the API documentation of the method in BufferedInputStream.

Also, read in the line below is not guaranteed to read the whole file in one go. It returns the number of bytes that were actually read, which can be less than what you asked for. And in the client code, you are using read in the same way, without actually checking if it read all the data.

阳光①夏 2024-12-01 08:51:38

请使用 FileUtilsIOUtils 检查 commons-io。这应该会让工作变得更加容易。

http://commons.apache.org/io/

Please check commons-io with FileUtils and IOUtils. This should make work a lot easier.

http://commons.apache.org/io/

烟酒忠诚 2024-12-01 08:51:38

在 Java 中复制流的正确方法如下:

int count;
byte[] buffer = new byte[8192]; // more if you like, but over a network it won't make much difference
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

您的代码在多个点上无法在逻辑上匹配。

此外,available() 也不是确定文件大小或传入网络传输大小的有效方法 - 请参阅 Javadoc。它几乎没有正确的用途,而且这不是其中的两个。

The correct way to copy a stream in Java is as follows:

int count;
byte[] buffer = new byte[8192]; // more if you like, but over a network it won't make much difference
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

Your code fails to logically match this at several points.

Also available() is not a valid way to determine either a file size or the size of an incoming network transmission - see the Javadoc. It has few if any correct uses and these aren't two of them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文