最近因為做一個監控系統,在其中用到了大量的socket。由於平時很少用到socket,在使用過程中還是遇到了一些問題的。比如:
1.socket一般在不主動關閉的情況下阻塞時間一般是有系統本身決定的(這個時間一般都很長)。
2.超時一般有連接超時,和讀寫超時。對於剛接觸socket的人很容易把代碼中提供的超時方法理解為連接超時。這就導致了一些錯誤,同時沒有達到自己的預期。(往往會奇怪我明明設置了超時時間,為什麼拋錯時間和自己設置的對不上)
在做連接監控的時候就用到了對socket的連接超時設置,由於對socket接觸的少就遇到了以上問題。
在項目中用的是java socket,在之後又看了一下go 的 socket。下面讓我們看一下他們各自的實現:
我們平時不加超時時間的時候一般都是:
java :
// 要連接的服務端IP地址和端口
String host = "192.168.1.7";
int port = 6000;
// 與服務端建立連接
Socket socket = null;
try {
socket = new Socket(host, port);
// 建立連接後獲得輸出流
int n = 0;
String message=this.getName() + "你好" + n;
socket.getOutputStream().write(message.getBytes("UTF-8"));
} catch (IOException e) {
if(num == 0){
System.out.println("我連接不上他");
}
num++;
TSocket tSocket = new TSocket();
tSocket.start();
e.printStackTrace();
}
go :
conn,err:=net.Dial("tcp","192.168.1.7:6000")
\tif err != nil {
\t\tfmt.Println(err)
\t}
\tstr := []byte{32, 0, 0, 0, 7, 85, 35, 160, 176, 7, 226, 12, 18, 15, 45, 0}
\t//向連接端發送一個數據
\t_,err=conn.Write(str)
\tif err != nil {
\t\tfmt.Println(err)
\t}
\t//讀取連接端返回來的數據,
\tresult,err:=ioutil.ReadAll(conn)
\tif err != nil {
\t\tfmt.Println(err)
\t}
\tfmt.Println(string(result))
在java中為我們socket.setSoTimeOut()來設置超時時間,在go中這是conn.SetDialLine(),conn.SetReadDialLine(),
conn.SetWriteDialLine()。
剛開始用socket的人會理所當然的認為這兩個是設置的連接超時。就會導致上面所說的問題。
java中的socket.setSoTimeOut()是設置socket的讀超時。設置後在讀超時後,就會拋出java.net.SocketTimeoutException: Read timed out。
go中的conn.SetDialLine()是設置socket的讀寫超時。相當於conn.SetReadDialLine()和conn.SetWriteDialLine()。同時conn.SetDialLine()設置的距離讀寫的結束時間,而不是直接就是設置每次讀寫的超時時間。
其實想實現對連接超時時間的設置很簡單,java和go都為我們實現了:
java:
socket = new Socket(host, port);
修改為:
socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 5000);//地址,超時時間
go:
conn,err:=net.Dial("tcp","192.168.1.7:6000")
修改為 :
conn,err:=net.DialTimeOut("tcp","192.168.1.7:6000",5*time.Second)//連接類型,地址,超時時間
在java中通過socket.connect()超時時間,同時單位是毫秒。
在go中通過net.DialTimeOut設置。
————————————————
原文鏈接:https://blog.csdn.net/aixinaxc/article/details/89208107
閱讀更多 雨竹165179353 的文章