2013-03-01 15 views
13

Devo gestirlo in modo diverso quando prendo lo SocketTimeoutException. L'unica cosa che trovo è affidarsi allo getMessage(). Finora ne ho trovati due:Come differenziare SocketTimeoutException

I messaggi (connessione scaduta, lettura scaduta) sono codificati? Dove vengono generati? Almeno qualsiasi valore costante per quei messaggi?

+0

Molto buono da chiedere prima! In genere, è una cattiva idea analizzare i messaggi. Hai controllato se puoi usare 'getCause()' per vedere cosa sta causando l'eccezione? –

+1

Inoltre, esiste anche un campo 'bytesTransferred'. Controlla se questo cambia in base alla causa dell'eccezione. –

+1

Uno è lanciato da 'connect()' uno è lanciato da un 'read()' ... non hai * * * per distinguere tra i due. –

risposta

2

Quindi, ecco la mia pretesa di fama. Qui, stiamo camminando lungo lo StackTrace, cercando il metodo di origine dell'eccezione.

public class ExceptionOriginTracing { 

    public static void main(String[] args){ 
     try { 
      originOne(); 
      originTwo(); 
     } catch (Exception e){ 
      // Now for the magic: 
      for (StackTraceElement element : e.getStackTrace()){ 
       if (element.getMethodName().equals("originOne")){ 
        System.out.println("It's a read error!"); 
        break; 
       } else if (element.getMethodName().equals("originTwo")){ 
        System.out.println("It's a write error!"); 
        break; 
       } 
      } 
     } 
    } 

    public static void originOne() throws Exception{ 
     throw new Exception("Read Failed...", null); 
    } 

    public static void originTwo() throws Exception{ 
     throw new Exception("Connect failed...", null); 
    } 
} 

La differenza per l'analisi del messaggio proposta dal eccezione è, che una semplice stringa è più propensi a cambiare, che il nome del metodo attuale.

A parte questo, questa non è una soluzione ottimale! Ma purtroppo non esiste una soluzione ottimale qui.

Inoltre, con questo approccio, cura supplementare deve essere presa quando l'offuscamento di origine viene utilizzato, che cambierà il metodo nomi e per questo il valore di ritorno di getMethodName().


Il modo giusto quando progettando qualcosa di simile sarebbe quello di avvolgere l'eccezione in una nuova eccezione, che ha fornito i metodi per scoprire in realtà l'origine reale usando una bandiera o un enum.

Analizzare un messaggio/StackTrace si sente sempre sporco ed è subtable da interrompere nelle versioni future!

+0

Beh, probabilmente è il meglio che posso fare. Ho lo stacktrace completo. È improbabile che il nome di quei metodi venga modificato java.net.SocketInputStream.socketRead0 (metodo nativo) e java.net.PlainSocketImpl.socketConnect (metodo nativo). Ma nel frattempo non credo che i messaggi verranno modificati. "Time out lettura" e "timeout connessione". Sembrano essere nel codice nativo. Avviso "Timeout di lettura" con maiuscola "R" e "timeout di connessione" con lettere minuscole "c". A proposito, lo zoccolo si trova all'interno del livello di trasporto di Thrift, non voglio rovinarlo di sicuro –

+0

@WeiZhu è una situazione davvero disordinata. Forse una combinazione di entrambi funziona meglio, ma più volte, entrambi potrebbero cambiare nella prossima versione. Vorrei anche presentare un bug-report sul tracker di problemi di quella particolare libreria, chiedendo di aggiungere qualcosa per determinare quale fosse l'origine dell'eccezione. –

2

È possibile controllare Socket.isConnected. Ma poiché le eccezioni vengono lanciate con metodi diversi, è meglio usare due blocchi catch con azioni diverse.

try { 
     socket.connect(address); 
    } catch (SocketTimeoutException e) { 
     throw new SocketConnectionException(e); 
    } 
    try { 
     socket.getInputStream(); 
     ... 
    } catch (SocketTimeoutException e) { 
     throw new SocketReadException(e); 
    } 
+1

Stiamo usando una lib di terze parti che gestisce i socket. Ci sono più livelli sopra, non so quale metodo socket (connect vs read) getta esattamente l'eccezione. –

+0

quindi non vedo una buona soluzione per questo. Come soluzione alternativa è possibile verificare la presenza di Exception.getMessage() o Exception.getStackTrace() (secondo probabilmente più affidabile) – ijrandom

+0

che fanno venire dal metodo diverso: per la lettura viene da: causato da: java.net.SocketTimeoutException: Leggi timeout a java.net.SocketInputStream.socketRead0 (metodo natale) a java.net.SocketInputStream.read (fonte sconosciuta) Per collegarlo proviene da: causati da: java.net.SocketTimeoutException: connect timeout su java.net.PlainSocketImpl.socketConnect (metodo nativo) su java.net.PlainSocketImpl.doConnect (fonte sconosciuta) su java.net.PlainSocketImpl.connectToAddress (fonte sconosciuta) –

0

Vengono da diversi metodi. "Connection timeout" si verifica quando si chiama connect(), implicitamente o esplicitamente; 'tempo scaduto' si verifica quando si chiama read() o uno dei suoi analoghi. In questo modo puoi differenziare il fatto di avere due blocchi di cattura diversi. Ma in entrambi i casi probabilmente stai per chiudere la connessione ...

+0

Com'è diverso dalla risposta già fornita? –

+0

Per iniziare ci sono più informazioni, ma non sono consapevole che sia un crimine SO per la stessa risposta corretta apparire più di una volta per ogni domanda. Se lo è, c'è un terribile registro di pulizia da fare. – EJP

Problemi correlati