开发者

Socket: premature end of JPEG file

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


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.


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

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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜