connectTimeOut和readTimeout


網絡編程時,經常遇到很多 timeout異常,下面是java URLConnection 中經典的2種  timeout參數,這些參數設置不當的話,就會遇到 timeout 異常。

1. ConnectTimeout , java 是這樣解釋的。 意思是用來建立連接的時間。如果到了指定的時間,還沒建立連接,則報異常。

 

 

Sets a specified timeout value, in milliseconds, to be used when opening a communications link to the resource referenced by this URLConnection. If the timeout expires before the connection can be established, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout. 

Some non-standard implmentation of this method may ignore the specified timeout. To see the connect timeout set, please call getConnectTimeout().

 

經典異常如下所示:

 

java.net.SocketTimeoutException: connect timed out
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1491)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1485)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
    at 。。。。。。(Unknown Source)
Caused by: java.net.SocketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    at java.net.Socket.connect(Socket.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:564)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:395)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:530)
    at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:272)
    at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:329)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:172)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:911)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:158)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
    at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2300)
    at java.net.URLConnection.getHeaderFieldInt(URLConnection.java:579)
    at java.net.URLConnection.getContentLength(URLConnection.java:474)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContentLength(HttpsURLConnectionImpl.java:378)
    at 。。。。。。(Unknown Source)

 

通過 URLConnection setConnectTimeout 可以設置指定的值。0則指極大值。

        conn = url.openConnection();
                    
        conn.setConnectTimeout(5000);

 

2. ReadTimeout , java 是這樣解釋的。 意思是已經建立連接,並開始讀取服務端資源。如果到了指定的時間,沒有可能的數據被客戶端讀取,則報異常。

 

 

Sets the read timeout to a specified timeout, in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. If the timeout expires before there is data available for read, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout. 

Some non-standard implementation of this method ignores the specified timeout. To see the read timeout set, please call getReadTimeout().


 

類似報錯信息如下:

 

 

java.net.SocketTimeoutException: Read timed out
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1491)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1485)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1139)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
	at 。。。。。。(Unknown Source)
Caused by: java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
	at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:830)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
	at sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:2300)
	at java.net.URLConnection.getHeaderFieldInt(URLConnection.java:579)
	at java.net.URLConnection.getContentLength(URLConnection.java:474)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getContentLength(HttpsURLConnectionImpl.java:378)
	at 。。。。。。(Unknown Source)

 

通過 URLConnection setReadTimeout 可以設置指定的值。0則指極大值。

        conn = url.openConnection();

        conn.setReadTimeout(20000);

 

類似的設置在很多軟件都基本相同的,比如 wget.

 

 -T,  --timeout=SECONDS         set all timeout values to SECONDS.
      --dns-timeout=SECS        set the DNS lookup timeout to SECS.
      --connect-timeout=SECS    set the connect timeout to SECS.
      --read-timeout=SECS       set the read timeout to SECS.


 

 

 
 

,但是實際的情況是當時專網的時候(不能訪問百度)根本不是1.5秒拋出超時的異常,這個問題困擾2天,

也在網上查詢很多資料,結果有人說還要設置讀取超時conn.setReadTimeout(1500);結果一試還是不行,

就再找發現有人在使用的情況下查看控制台發現訪問1500毫秒之后系統會自動的嘗試很多次(集體多少次沒有算)

導致很長時間才拋出訪問超時異常,這樣導致我們看到的現象就是我設置了1500毫秒超時結果幾分鍾才給我超時異常,感覺設置的超時時間沒有效果。

 

那么說一下我的解決方法,我個人測試通過,如果有好的方法請指出:

因為系統會自動的嘗試很多次超時之后才給你拋出異常,所以我把這個異常超時時間設置短一點如我設置500毫秒,公網的情況下能正常的訪問,專網也能很快的拋出異常達到了我的目的。

另外判斷公網專網的另一種方法就是用ping ,記得要起一個服務區處理ping,關閉之后要殺死改進程,否則第二次ping可能就阻塞了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM