1. 程式人生 > >socket開發注意點

socket開發注意點


一 
socket自帶兩個通道, 一個接收,一個傳送, 互不影響, 通訊過程中,可關閉其中一個,或兩個一起關閉


二  isClosed()與isConnected

isClosed()方法來判斷某個Socket物件是否處於關閉狀態, 但並不是指連線是否關閉, 當然,如果物件關閉了,連線自然也就關閉, 但是連線關閉了,物件並不一定是關閉

isConnected()方法來判斷Socket物件是否曾經連線成功過, 此英文是過去式, 並不代表當前的真實連線狀態。

即使現在isClose返回true,isConnected仍然返回true。因此,要判斷當前的Socket物件是否處於連線狀態,必須同時使用isClosed()和isConnected()方法,即只有當isClosed()返回false,isConnected()返回true的時候Socket物件才處於連線狀態。

據分析,兩方法合併最有效的用於主動請求,即客戶端,  服務端accept()得到的 socket, isConnected肯定是true, 而isClosed並不能代表真實的連線是否關閉


當其中一方連線突然斷開,或意外斷開時, 會報Connection reset的錯誤訊息,可攔截此訊息來提示連線已斷開


三 關閉連線

1. socket.close()  關閉連線,

2. 當Socket類的InputStream和OutputStream只有一個關閉,就是半關閉狀態。

3. socket.shutdownOutput() ,要告訴對方已傳送結束, 並且關閉傳送通道, 


四 阻塞

socket.getIntputStream() 的 read() 會阻塞, 但執行了available() 之後, 下一次的read將不阻塞的從這個輸入流讀取(或跳過)的估計剩餘位元組數

InputStream is = this.clientSocket.getInputStream();
            
int c = is.available();

 byte[] b = new byte[c>1024?c:1024]; //由於是估計的剩餘位元組數, 所以保險一點
 int l = 0;
 l = is.read(b);//由於available()只用於下一次不阻塞,所以這裡不用while ((l=xx) != -1), 否則會阻塞
 strb.append(new String(b,0,l));
 

五 超時

setSoTimeout(int);  此超時的方法並不是值連線超時, 只是read()超時, 即在規定的時間內, 還沒有read()到資料,就報SocketException超時錯誤, 而socket仍然是有效的,  此超時記錄還是累加的,假設超時定了5秒,每read()一次都用2秒, 第三次就會超時,此方法可以理解為定義read阻塞超時,在whlie裡面定義,可以起到部分作用


六,判斷連線
當客戶端意外埠時, 有時socket會變成半關閉狀態,傳送並不會報異常,檢測連線的最有效辦法是傳送心跳包,每個心跳都記錄時間,當迴應的時間超過規定時間,當作掉線處理