套接字:JPEG 文件过早结束
我正在尝试通过套接字将图像文件从服务器发送到客户端。 套接字以前用于将一些字符串从服务器发送到客户端(使用缓冲的输入/输出流)。
问题是无法正确接收图像文件,出现“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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
错误最有可能出现在此处:
方法
available
不返回文件的大小。它可能只返回输入缓冲区的大小,该大小小于文件的大小。请参阅 BufferedInputStream 中该方法的 API 文档。另外,下面一行中的
read
不能保证一次性读取整个文件。它返回实际读取的字节数,该数可能小于您要求的字节数。在客户端代码中,您以相同的方式使用read
,而无需实际检查它是否读取了所有数据。The error is most likely here:
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 inBufferedInputStream
.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 usingread
in the same way, without actually checking if it read all the data.请使用
FileUtils
和IOUtils
检查 commons-io。这应该会让工作变得更加容易。http://commons.apache.org/io/
Please check commons-io with
FileUtils
andIOUtils
. This should make work a lot easier.http://commons.apache.org/io/
在 Java 中复制流的正确方法如下:
您的代码在多个点上无法在逻辑上匹配。
此外,available() 也不是确定文件大小或传入网络传输大小的有效方法 - 请参阅 Javadoc。它几乎没有正确的用途,而且这不是其中的两个。
The correct way to copy a stream in Java is as follows:
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.