首頁 >Java >Java基礎 >Java中對Socket設定超時時間

Java中對Socket設定超時時間

尚
轉載
2019-11-28 17:17:055300瀏覽

Java中對Socket設定超時時間

java中對Socket設定逾時時間主要有以下兩種方式,我們來看看:(推薦:java影片教學

方式1:

Socket s=new Socket(); 
s.connect(new InetSocketAddress(host,port),10000);

方式2:

Socket s=new Socket("127.0.0.1",8080);
s.setSoTimeout(10000);

那麼這兩種方式設定的超時時間各自代表了什麼意義呢?有什麼區別呢?

第1種方式

我們先來看第1種方式,我們來測試一下:

在main 方法中我們建立Socket連接到

ip :29.212.19.201,連接埠:2132

public static void main(String[] args) {
    Socket socket = new Socket();
    SocketAddress endpoint = new InetSocketAddress("29.212.19.201", 2132);
    long timeMillis = System.currentTimeMillis();
    try {
      socket.connect(endpoint, 10000);
    } catch (IOException e) {
      e.printStackTrace();
    }
    System.out.println(System.currentTimeMillis()-timeMillis);
    System.out.println("end");
  }

運行這段程式碼,控制台10秒之前沒有任何資訊輸出,10秒後列印以下訊息:

10002
java.net.SocketTimeoutException: connect timed out
  at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at com.wakling.cn.SocketSever.main(SocketSever.java:33)
end

可以看出,我們嘗試連接到29.212.19.201:2132時,連接了10秒都沒有連接上,於是就報了java.net.SocketTimeoutException: connect timed out 的異常。

解釋一下,上述的 IP 是一個未知的 IP ,即我的 IP 在當前網路環境中存取不到這個 IP ,這樣我們的這個 Socket 才會去一直嘗試連接到此 IP 直到逾時。如果 IP 是已知的 IP ,例如本地 127.0.0.1 加上一個未知的端口,那麼此 Socket 連線會立刻報錯。

另外,在不設定連線逾時時間的情況下,Socket 預設大概是21s(測試了3次都是21020毫秒)連線逾時。如下是不設定連接逾時時間的程式碼:

Socket socket = new Socket("29.212.19.201", 2132);

第2種方式

然後我們來看第2種方式,這時候我們需要在我們本地寫一套Socket 服務以及客戶端來模擬這個場景。

我們讓客戶端設定 setSoTimeout 為10s,在服務端程式碼拿到客戶端請求訊息後,休眠10s後再處理客戶端請求,回傳回應。

我們來看看效果,關鍵程式碼如下:

//服务端
System.out.println("进入休眠,10s后醒来");
Thread.sleep(10000);
System.out.println("休眠结束");
//返回响应
OutputStream outputStream = socket.getOutputStream();// 获取一个输出流,向服务端发送信息
PrintWriter printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
printWriter.print("你好,服务端已接收到您的信息");
printWriter.flush();

//客户端
Socket socket = new Socket("127.0.0.1",2132);
socket.setSoTimeout(10000);//read的超时时间

運行後,等待客戶端輸出,10s後客戶端控制台輸出資訊如下:

java.net.SocketTimeoutException: Read timed out
  at java.net.SocketInputStream.socketRead0(Native Method)
  at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
  at java.net.SocketInputStream.read(SocketInputStream.java:171)
  at java.net.SocketInputStream.read(SocketInputStream.java:141)
  at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
  at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
  at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
  at java.io.InputStreamReader.read(InputStreamReader.java:184)
  at java.io.BufferedReader.fill(BufferedReader.java:161)
  at java.io.BufferedReader.readLine(BufferedReader.java:324)
  at java.io.BufferedReader.readLine(BufferedReader.java:389)
  at com.wakling.cn.SocketClient.main(SocketClient.java:36)
10020
end

這裡10s後客戶端報錯java.net.SocketTimeoutException: Read timed out 查看客戶端控制台資訊正常輸出,即使客戶端已報逾時,服務端仍繼續往下走,只是客戶端已經收不到服務端10s後發給自己的消息。

另外經過測試發現,服務端休眠很久很久,如500s,在客戶端不設定 setSoTimeout 時,預設120s逾時。

區別與意義

下面我們就來說一說二者的意義和差異。

方式1是客戶端與服務端連線的逾時時間,也就是10秒內建立不了連線就報java.net.SocketTimeoutException: connect timed out 連線逾時的例外狀況。此時二者未建立連接,更別說服務端收到客戶端的訊息了。

方式2是設定inputStream.read() 方法的阻塞時間,也就是客戶端發出請求後等待服務端回傳回應的等待時長,超過這個時長將會引發java.net.SocketTimeoutException: Read timed out異常。此時二者正常建立連接,服務端接收到了客戶端的請求。

兩種方式控制超時的重點不同,就像打電話一樣,方法1是打電話10秒你不接電話我就掛了,方法2是打電話接通後,等你10秒不說話就掛,10秒後說不說話都不聽了。

更多java知識請關注java基礎教學欄。

以上是Java中對Socket設定超時時間的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除