2011-04-19 57 views
4

我試圖將套接字連接到一個不存在的服務器,我真的不明白爲什麼一個例外是被提出。插座不拋出異常,雖然他無法連接

這裏是我的代碼:

public class TestSocket extends Activity { 
    private static final String TAG = "TestSocket"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     BasicThread t = new BasicThread(); 
     t.start(); 
    } 

    class BasicThread extends Thread { 
     @Override 
     public void run() { 
      Log.d(TAG, "Before"); 
      try { 
       new Socket("42.42.42.42", 12345); 
       Log.d(TAG, "Connected"); 
      } catch (Exception e) { 
       Log.d(TAG, "Exception"); 
      } 
      Log.d(TAG, "After"); 
     } 
    } 
} 

我還試圖用我自己的IP地址,而運行Wireshark的,我第一次從Android的從我的電腦得到[SYN]我的電腦,然後[RST, ACK]到Android(因爲沒有什麼是在此端口監聽),但我仍然沒有在Android上遇到異常情況。

另外我正在測試一個物理電話(Nexus S),並且在我的Manifest中確實有互聯網許可。

爲什麼我沒有收到Exception

編輯:

更準確地說,輸出我得到的是

D/TestSocket(17745): Before 
D/TestSocket(17745): Connected 
D/TestSocket(17745): After 

(而不是Exception

回答

0

在插座的構造,它拋出當主機的IP地址不能確定,所以我認爲,因爲你沒有傳遞需要解析的主機名,所以會拋出一個不同的異常。我相信這個異常實際上來自URL類或者其他解決方案,並且無處不在。

連接(..)方法應該拋出一個異常,但不會像你說的那樣出現。

編輯:顯然Android(一些版本)在這裏不能正常工作,所以它可能是一個bug:http://code.google.com/p/android/issues/detail?id=6144。它看起來並不像我想象的那樣是指向模擬器。

+0

是的,我期待IOException被拋出,但事實並非如此,什麼都不會拋出。 – 2011-04-19 15:14:57

+0

我期望它吞下異常(我曾經有編碼模擬替換Socket的經驗,構造函數對異常處理來說確實是一團糟)。您可以嘗試使用無參數構造函數創建一個Socket,然後明確調用connect並查看是否會得到一個異常。你也可以在構造函數之後檢查套接字的連接狀態,然後拋出你自己的IOException,或者只是失敗:) – 2011-04-19 15:19:35

+0

我試過了(用Joseph Earl的答案代碼),並且我有完全相同的結果。 – 2011-04-19 15:21:17

0

有很多事情會導致套接字連接失敗,併發生異常。

但是,如果TCP協議發送SYN消息以啓動連接過程是

  • 防火牆阻止,
  • 通過borked網絡路由選擇或
  • 路由到一些端點沒有響應,

然後發起計算機上的TCP堆棧將只是重試,然後重試。如果您設置了連接超時,您最終會得到異常,但可能需要很長時間。


它在Android模擬器上工作而不在真實設備上的事實僅僅意味着它們的實現或配置不同。 (例如,它們可能具有不同的默認連接超時......模擬器可能被設計爲在該場景中拒絕連接。)

底線是您需要使您的代碼在真實設備上工作。找出讓設備設置連接超時的最佳方式,並檢查在與不存在的服務器通話時工作的方式。

+0

某些事情確實以'[RST,ACK]'數據包做出響應,我猜(這個數據包)意味着這裏沒有人在聽。順便說一下,我試着用模擬器,我有一個'ConnectException:Connection refused'。但是這在我的手機上不起作用。 – 2011-04-19 15:41:41

+0

重試次數以及它們之間的間隔由TCP/IP的操作系統實現決定,而Java不提供查找這些值或更改它們的方法。但是,Java *應該在超時過期時爲未連接的套接字引發一個異常。它可能是無限的,但是連續的代碼不會被執行。 – 2011-04-19 15:42:52

+0

我認爲應將RST(重置)響應映射到「連接被拒絕」。 – 2011-04-20 02:16:43

-2

您的try catch代碼不會捕獲IO異常。嘗試這樣的事情

try 
{ 
    // to get the ip address of the server by the name<br> 
    InetAddress ip =InetAddress.getByName("example.com"); 

    sock= new Socket(ip,Server.PORT); 
    ps= new PrintStream(sock.getOutputStream()); 
    ps.println(" Hi from client"); 
    DataInputStream is = new 
    DataInputStream(sock.getInputStream()); 
    System.out.println(is.readLine()); 
}catch(SocketException e){ 
    System.out.println("SocketException " + e); 
}catch(IOException e){ 
    System.out.println("IOException " + e); 
} 
+2

我的代碼捕獲每個異常,包括IOException。 – 2011-04-19 18:19:34