1. 程式人生 > >java socket SocketException 幾個常見異常

java socket SocketException 幾個常見異常

1.java.net.SocketTimeoutException.這個異常比較常見,socket超時.一般有2個地方會丟擲這個,一個是connect的時候,這個超時引數由connect(SocketAddress endpoint,int timeout)中的後者來決定,還有就是setSoTimeout(int timeout),這個是設定讀取的超時時間.它們設定成0均表示無限大.

2.java.net.BindException:Address already in use: JVM_Bind.該異常發生在伺服器端進行new ServerSocket(port) 或者socket.bind(SocketAddress bindpoint)操作時.
原因:與port一樣的一個埠已經被啟動,並進行監聽.此時用netstat Can命令,可以看到一個Listending狀態的埠.只需要找一個沒有被佔用的埠就能解決這個問題.

3.java.net.ConnectException: Connection refused: connect.該異常發生在客戶端進行new Socket(ip, port)或者socket.connect(address,timeout)操作時.
原因:指定ip地址的機器不能找到(也就是說從當前機器不存在到指定ip路由),或者是該ip存在,但找不到指定的埠進行監聽.應該首先檢查客戶端的ip和port是否寫錯了,假如正確則從客戶端ping一下伺服器看是否能ping通,假如能ping通(服務伺服器端把ping禁掉則需要另外的辦法),則看在伺服器端的監聽指定埠的程式是否啟動.

4.java.net.SocketException: Socket is closed,該異常在客戶端和伺服器均可能發生.異常的原因是己方主動關閉了連線後(呼叫了Socket的close方法)再對網路連線進行讀寫操作.

5.java.net.SocketException: Connection reset或者Connect reset by peer:Socket write error.該異常在客戶端和伺服器端均有可能發生,引起該異常的原因有兩個,第一個就是假如一端的Socket被關閉(或主動關閉或者因為異常退出而引起的關閉),另一端仍傳送資料,傳送的第一個資料包引發該異常(Connect reset by peer).另一個是一端退出,但退出時並未關閉該連線,另一端假如在從連線中讀資料則丟擲該異常(Connection reset).簡單的說就是在連線斷開後的讀和寫操作引起的.
對於伺服器,一般的原因可以認為:
a) 伺服器的併發連線數超過了其承載量,伺服器會將其中一些連線主動Down掉.
b) 在資料傳輸的過程中,瀏覽器或者接收客戶端關閉了,而服務端還在向客戶端傳送資料.

6.java.net.SocketException: Broken pipe.該異常在客戶端和伺服器均有可能發生.在丟擲SocketExcepton:Connect reset by peer:Socket write error後,假如再繼續寫資料則丟擲該異常.前兩個異常的解決方法是首先確保程式退出前關閉所有的網路連線,其次是要檢測對方的關閉連線操作,發現對方關閉連線後自己也要關閉該連線.
對於4和5這兩種情況的異常,需要特別注意連線的維護.在短連線情況下還好,如果是長連線情況,對於連線狀態的維護不當,則非常容易出現異常.基本上對長連線需要做的就是:
a) 檢測對方的主動斷連(對方呼叫了Socket的close方法).因為對方主動斷連,另一方如果在進行讀操作,則此時的返回值是-1.所以一旦檢測到對方斷連,則主動關閉己方的連線(呼叫Socket的close方法).
b) 檢測對方的宕機、異常退出及網路不通,一般做法都是心跳檢測.雙方週期性的傳送資料給對方,同時也從對方接收“心跳資料”,如果連續幾個週期都沒有收到對方心跳,則可以判斷對方或者宕機或者異常退出或者網路不通,此時也需要主動關閉己方連線;如果是客戶端可在延遲一定時間後重新發起連線.雖然Socket有一個keep alive選項來維護連線,如果用該選項,一般需要兩個小時才能發現對方的宕機、異常退出及網路不通.

7.java.net.SocketException: Too many open files
原因: 作業系統的中開啟檔案的最大控制代碼數受限所致,常常發生在很多個併發使用者訪問伺服器的時候.因為為了執行每個使用者的應用伺服器都要載入很多檔案(new一個socket就需要一個檔案控制代碼),這就會導致開啟檔案的控制代碼的缺乏.
解決方式:
a) 儘量把類打成jar包,因為一個jar包只消耗一個檔案控制代碼,如果不打包,一個類就消耗一個檔案控制代碼.
b) java的GC不能關閉網路連線開啟的檔案控制代碼,如果沒有執行close()則檔案控制代碼將一直存在,而不能被關閉.也可以考慮設定socket的最大開啟數來控制這個問題.對作業系統做相關的設定,增加最大檔案控制代碼數量.ulimit -a可以檢視系統目前資源限制,ulimit -n 10240則可以修改,這個修改只對當前視窗有效.