2013-04-18 11 views
5

Qualcuno ha più informazioni utili sull'eccezione "Riprova"?"IOException: riprova" mentre si utilizza LocalServerSocket

sto inviando bitmap tra app mediante LocalServerSocket e LocalSocket:

uscita:

socket = new LocalSocket(); 
socket.connect(new LocalSocketAddress(SOCKET_NAME)); 
fos = new DataOutputStream(socket.getOutputStream()); 
... 

public void onEvent() { 
    fos.writeInt(width); 
    fos.writeInt(height); 
    fos.writeInt(newBuffer.length); 
    fos.write(newBuffer); 
} 

ingresso:

server = new LocalServerSocket(SOCKET_NAME); 
socket = server.accept(); 
socket.setSoTimeout(60); 

while(true) { 

    int width = fis.readInt(); // IO Exception being thrown here 
    int height = fis.readInt(); 
    int length = fis.readInt(); 
    byte[] bytes = new byte[length]; 
    fis.read(bytes); 
} 

[try/catch ecc rimossi per chiarezza]

04-18 09:19:11.664: W/System.err(1268): java.io.IOException: Try again 
04-18 09:19:11.664: W/System.err(1268):  at android.net.LocalSocketImpl.readba_native(Native Method) 
04-18 09:19:11.664: W/System.err(1268):  at android.net.LocalSocketImpl.access$400(LocalSocketImpl.java:29) 
04-18 09:19:11.664: W/System.err(1268):  at android.net.LocalSocketImpl$SocketInputStream.read(LocalSocketImpl.java:92) 
04-18 09:19:11.664: W/System.err(1268):  at libcore.io.Streams.readFully(Streams.java:81) 
04-18 09:19:11.664: W/System.err(1268):  at java.io.DataInputStream.readInt(DataInputStream.java:124) 
04-18 09:19:11.664: W/System.err(1268):  at com.test.util.BitmapSendingUtils$BitmapReceiver$1.run(BitmapSendingUtils.java:105) 

risposta

3

Da quel momento non ho potuto trovare la soluzione. Ma mentre la sua attuazione un modo diverso mi sono imbattuto in questi errori nel codice originale:

byte[] bytes = new byte[length]; 
fis.read(bytes); 

dovrebbe essere:

byte[] content = new byte[length]; 
int read = is.read(content); 
while(read < content.length) { 
    read += is.read(content, read, content.length - read); 
} 

come .read(byte[]) non slurp il tutto in una sola volta. Supponevo che questo continuasse a gorgogliare e bloccare continuamente mentre lo faceva.

c'è anche questo:

socket.setSoTimeout(60); 

L'arg è a Millis, piuttosto che secondi in modo dovrebbe essere:

socket.setSoTimeout(60 * 1000); 

io ancora non so la causa di quanto sopra un'eccezione male di nome anche se così spero che qualcuno risponda a questo se lo sanno!

4

L'eccezione che si vede è probabilmente l'equivalente java dell'errore EAGAIN. Vedi ad esempio this answer.

È necessario gestire l'eccezione e riprovare l'operazione IO non riuscita.

+0

Il lancio su una specifica operazione di blocco. Non sembra che la risposta di cui sopra si applica. Beh, non dovrebbe comunque. – Graeme

+0

Ah, capisco. È un bug in LocalSocketImpl? Cosa succede se trattate l'errore come EAGAIN e provate ancora? –

+0

Per favore, facci sapere come hai risolto questo problema –

0

prova come flusso, usare mInputValid per controllare se terminare il flusso:

private int fill(byte[] buffer, int offset,int length) throws IOException { 
    int sum = 0, len; 
    while ((sum<length) && mInputValid) { 
     try{ 
      len = is.read(buffer, offset + sum, length - sum); 
      if (len < 0) { 
       throw new IOException("End of stream"); 
      } else{ 
       sum += len; 
       Log.i(TAG, "is.read: " + len + " buffer:" + buffer[0]); 
      } 
     } 
     catch (IOException e){ 
      e.printStackTrace(); 
      Log.i(TAG, "read input fail, try again"); 
      continue; 
     } 
    } 
    return sum; 
} 
0

Penso che la "Prova di nuovo" IOException dovrebbe in realtà essere gestito allo stesso modo un SocketTimeoutException sarebbe stato gestito. Si tratta di un API molto male implementata, ma siamo abituati a tale disegno di merda su Android:

private int read(byte[] buffer) throws IOException { 

    while (true) { 
     try { 
      return fis.read(buffer); 
     } catch (SocketTimeoutException e) { 
      continue; 
     } catch (IOException e) { 
      String message = e.getMessage(); 
      if (message != null && message.equals("Try again")) { 
       continue; 
      } 
      throw e; 
     } 
    } 
} 

private int readInt() throws IOException { 
    while (true) { 
     try { 
      return fis.readInt(); 
     } catch (SocketTimeoutException e) { 
      continue; 
     } catch (IOException e) { 
      String message = e.getMessage(); 
      if (message != null && message.equals("Try again")) { 
       continue; 
      } 
      throw e; 
     } 
    } 
} 
0

So di essere in ritardo alla festa, ma ho appena risolto lo stesso problema e ci sono una serie di cose che può causare ciò:

  1. Non chiamare outputStream.flush() all'invio. Se usi i writer, è writer.flush(). Questo invia l'ultimo buffer. Se non si utilizzano i buffer, ciò non significa che non ci siano. Il flusso invia i dati in byte, quindi a meno che non invii un singolo byte, è probabile che ci sia un buffer lungo la linea che non viene inviato e il ricevitore riceve un mezzo int.
  2. Se si stanno mantenendo aperti i flussi, non c'è modo di rilevare la fine del flusso: quindi Java genererà un'eccezione se si tenta di fare cose come reader.read(buffer), quando la dimensione dello buffer supera la quantità di dati inviati. In questo caso è necessario implementare una sorta di prototipo (intestazione che indica la lunghezza o una sorta di token finale, per sapere quando interrompere la lettura).
  3. Se si stanno chiudendo i flussi dopo aver inviato un messaggio e chiamando output.flush(), questa eccezione può essere causata da ciò che si è inteso: timeout del socket, oltre che disconnessioni.
Problemi correlati