Сокет: преждевременный конец файла JPEG - PullRequest
0 голосов
/ 14 июля 2011

Я пытаюсь отправить файл изображения с сервера на клиент через сокет. Сокет ранее использовался для отправки некоторых строк с сервера клиенту (с буферизованными потоками ввода / вывода).

Проблема в том, что файл изображения не может быть получен должным образом с ошибкой «Преждевременный конец файла JPEG».

Сервер сначала отправляет клиенту размер файла, затем клиент создает байт [] этого размера и начинает получать файл.

Вот коды:

Сервер:

        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 ]

1 голос
/ 14 июля 2011

Ошибка, скорее всего, здесь:

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

Метод available не возвращает размер файла.Может возвращать только размер входного буфера, который меньше размера файла.См. Документацию API метода в BufferedInputStream.

. Кроме того, read в строке ниже не гарантирует, что весь файл будет прочитан за один раз.Возвращает количество фактически прочитанных байтов, которое может быть меньше, чем вы запрашивали.И в коде клиента вы используете read таким же образом, фактически не проверяя, прочитал ли он все данные.

1 голос
/ 14 июля 2011

Пожалуйста, проверьте commons-io с FileUtils и IOUtils. Это должно облегчить работу.

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

0 голосов
/ 15 июля 2011

Правильный способ копирования потока в 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);
}

Ваш код не может логически соответствовать этому в нескольких точках.

Недоступно также () недопустимоспособ определения размера файла или размера входящей сетевой передачи - см. Javadoc.У него мало правильных применений, и это не два из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...