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會變成半關閉狀態,傳送並不會報異常,檢測連線的最有效辦法是傳送心跳包,每個心跳都記錄時間,當迴應的時間超過規定時間,當作掉線處理