套接字:JPEG文件的过早结束

时间:2011-07-14 13:06:49

标签: java io

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

问题是无法正确接收图像文件,“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秒,那么图像就会被正确接收。我想知道服务器和客户端之间是否存在某种竞争条件

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

错误很可能在这里:

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

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

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

答案 2 :(得分:0)

在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。它几乎没有正确的用途,这些不是两个。