0

Я создаю сервер для получения как текстовых, так и двоичных данных от клиентов. Он работает с текстовыми данными, а также с первым приемом двоичного файла, но после этого он не продолжает читать данные и генерирует исключение. Вот мой код сервера:Почему DataInputStream продолжает получать данные после чтения двоичного файла

public class ConnectedProcessThread implements Runnable{ 
    private final Socket socket; 

    public ConnectedProcessThread(Socket clientSocket){ 
     socket = clientSocket; 
    } 

    public void run(){ 
     DataInputStream dis = null; 
     try{ 
      while(true) { 
       dis = new DataInputStream(socket.getInputStream()); 
       String meta = dis.readUTF(); 
       Log.i("Data received", meta); 
       if(meta.equalsIgnoreCase("Text")){ 
        String message = dis.readUTF(); 
        Log.i("Data received", message); 
       }else if(meta.equalsIgnoreCase("Binary")){ 
        InputStream is = socket.getInputStream(); 
        ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
        byte[] buf = new byte[4096]; 
        int len; 
        while((len=is.read(buf))>-1){ 
         stream.write(buf,0,len); 
        } 
        stream.flush(); 

        //read object input 
        try { 
         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray())); 
         byte[] buffer = (byte[])ois.readObject(); 
         FileOutputStream fos = new FileOutputStream("/storage/emulated/0/DCIM/IMG-Saved.jpeg"); 
         fos.write(buffer); 
        }catch (ClassNotFoundException e){ 
         e.printStackTrace(); 
        } 
        finally { 
         Log.i("Binary_Transfer","File created"); 
        } 
       } 
      } 
     } catch (IOException e){ 
      e.printStackTrace(); 
     }finally { 
      Log.i("Client_Socket","Stream will close"); 
      if(dis!=null){ 
       try { 
        dis.close(); 
       }catch (IOException e){ 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

для текста и двоичных данных, перед передачей данных, клиент будет отправлен текст мета-данные, чтобы сообщить серверу данных является текстовым или двоичным. Но после получения файла (изображения) он генерирует исключение EOF в строке: String meta = dis.readUTF(); Я догадался, что это произошло, потому что после чтения и записи двоичного файла поток продолжает цикл, так что DataInputStream будет читать снова, и теперь нет ничего, чтобы получить так что readUTF() вызывает EOFException. Я попытался отправить метаданные от клиента после отправки двоичного файла, чтобы DataInputStream мог что-то прочитать и не выкидывать исключение, но он не работал, клиент действительно отправил метаданные, но сервер все еще бросает EOFException. Кто-нибудь знает, в чем проблема? Спасибо.

Вот мой отправить бинарный метод от клиента:

public void sendBinaryData(byte[] binaryData){ 
    if(dos!=null && socket!=null){ 
     try { 
      ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); 
      oos.writeObject(binaryData); 
      Log.d("Binary_Transfer", "C: Sent."); 
      oos.close(); 
      dos.writeUTF("Binary_End"); 
      dos.flush(); 
     }catch (Exception e){ 
      Log.e("File_Exception",e.toString()); 
     } 
    } 
} 

ответ

1

Потому что, когда вы начинаете читать двоичные данные, вы вводите цикл, который заканчивается только в конце потока, т.е. когда вызов разъединяется:

while((len=is.read(buf))>-1){ 
    stream.write(buf,0,len); 
} 

В этот момент вы находитесь в конце потока. Больше данных не было, данных больше нет, и данных больше не будет.

Вы должны полностью удалить эту часть:

InputStream is = socket.getInputStream(); 
ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
byte[] buf = new byte[4096]; 
int len; 
while((len=is.read(buf))>-1){ 
    stream.write(buf,0,len); 
} 
stream.flush(); 

Существует редко любой точки в чтении вещей в ByteArrayOutputStreams так или иначе, и это не является исключением. Просто удалите, что полностью, и изменить следующую часть:

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray())); 

в

ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); 

и продолжают, как вы уже. Однако у вас есть еще одна проблема:

oos.close(); 

Это закрывает розетку. Поэтому следующая часть:

dos.writeUTF("Binary_End"); 
dos.flush(); 

не может работать. Просто промойте ObjectOutputStream, а не закрывайте его.

Но я настоятельно рекомендую вам отказаться от DataInput/OutputStreams и использовать один ObjectInput/OutputStream для срока службы разъема на обоих концах.

+0

бит ключа, конечно, заключается в том, что OP должен использовать 'readObject()' для чтения 'byte []' на принимающей стороне. – jtahlborn

+0

@jtahlborn Прочтите его код. Это именно то, что он уже делает. Его проблема заключается в мусоре перед ним и закрытии 'ObjectOutputStream'. – EJP

+0

ah, внутри потока вложенных объектов. по какой-то причине я прояснил прошлое и вчера вечером. – jtahlborn

Смежные вопросы