2013-04-18 20 views
5

Czy ktoś ma więcej przydatnych informacji na temat wyjątku "Spróbuj ponownie"?"Wyjątek IOException: spróbuj ponownie" podczas korzystania z LocalServerSocket

wyślę bitmapy między aplikacjami za pomocą LocalServerSocket i LocalSocket:

wyjściowa:

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); 
} 

Wejście:

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 itp usuniętymi dla jasności]

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) 

Odpowiedz

3

Od tego czasu przepisałem to, ponieważ nie mogłem znaleźć rozwiązania. Ale podczas jej wdrażania w inny sposób natknąłem się tych błędów w oryginalnym kodzie:

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

Powinno być:

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

jak .read(byte[]) nie slurp całość naraz. Przyjąłem, że to ciągle się sypie i blokuje, podczas gdy to robił.

Jest to również:

socket.setSoTimeout(60); 

arg jest w Millis zamiast sekund tak powinno być:

socket.setSoTimeout(60 * 1000); 

ja nadal nie wiem przyczynę powyższej źle nazwie wyjątkiem choć mam nadzieję, że ktoś nadal będzie odpowiadał na to, jeśli wie!

4

Wyjątek, który widzisz, jest prawdopodobnie odpowiednikiem błędu EAGAIN w języku Java. Zobacz na przykład: this answer.

Powinieneś obsłużyć wyjątek i ponowić próbę operacji IO.

+0

Jego rzucanie na konkretną operację blokowania. Nie wygląda na to, że powyższa odpowiedź ma zastosowanie. Cóż, nie powinno tak być. – Graeme

+0

Ah, rozumiem. Czy to błąd w LocalSocketImpl? Co się stanie, jeśli potraktujesz błąd jako EAGAIN i spróbujesz ponownie? –

+0

Proszę dać znać, jak rozwiązałeś ten problem –

0

spróbować jak przepływ, użyj mInputValid kontrolować czy zatrzymania przepływu:

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

myślę „Spróbuj ponownie” IOException powinny rzeczywiście być traktowane w taki sam sposób SocketTimeoutException będą obsługiwane. To bardzo źle wdrożone API, ale jesteśmy przyzwyczajeni do tak brzydko projektu na Androida:

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

wiem, że jestem późno do partii, ale ja po prostu rozwiązać ten sam problem i istnieje wiele rzeczy, które może to spowodować:

  1. Nie dzwoniąc pod numer outputStream.flush() po wysłaniu. Jeśli używasz pisarzy, jest to writer.flush(). Spowoduje to wysłanie ostatniego bufora. Jeśli nie korzystasz z buforów, nie oznacza to, że ich tam nie ma. Strumień wysyła dane w bajtach, więc jeśli nie wysyłasz pojedynczego bajtu, jest szansa, że ​​w linii nie ma jakiegoś bufora, który nie zostanie wysłany, a odbiorca dostaje połowę int.
  2. Jeśli utrzymujesz strumienie otwarte, nie ma możliwości wykrycia końca strumienia, więc Java wyrzuci wyjątek, jeśli spróbujesz zrobić coś w rodzaju reader.read(buffer), gdy rozmiar buffer przekroczy ilość wysłanych danych. W tym przypadku musisz zaimplementować prototok (nagłówek informujący o długości lub jakimś tokenie końcowym, aby wiedzieć, kiedy przerwać czytanie).
  3. Jeśli zamykasz strumienie po wysłaniu wiadomości i wywołaniu output.flush(), ten wyjątek może być spowodowany przez to, co masz na myśli: przekroczenie limitu czasu gniazd, a także rozłączenia.
Powiązane problemy