圖文詳解OkHttp的超時時間
前言
雖然網(wǎng)上有很多關于okhttp超時時間的文章但大多都一筆帶過并沒有進行詳細的講解各自的作用,于是就看了下源碼大致寫一下其中的發(fā)現(xiàn).
本文以 'com.squareup.okhttp3:okhttp:3.12.0'源碼為參考
首先我們一共可以設置5個超時時間分別如下:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.callTimeout(120, TimeUnit.SECONDS)
.pingInterval(5, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
其中callTimeout,readTimeout,writeTimeout和okio的AsyncTimeout有著密不可分的關系,其內部維護了一個Watchdog,單獨開一個線程死循環(huán)判斷是否超時

connectTimeout:
指的是建立連接所用的時間,適用于網(wǎng)絡狀況正常的情況下,兩端連接所用的時間。
通過跟源碼發(fā)現(xiàn)這個值用在了 socket.connect(address, connectTimeout);
callTimeout:
這個值從調用call.execute();和enqueue();這兩個方法開始計時,時間到后網(wǎng)絡還未請求完成將調用cancel();方法
在RealCall類中可以看到在構造方法中創(chuàng)建timeout匿名內部類

在execute方法中開始計時

在timeoutExit方法中結束計時

pingInterval
通過跟源碼我們可以看到,這個值只有http2和webSocket中有使用


如果設置了這個值會定時的向服務器發(fā)送一個消息來保持長連接



所以在寫websocket時是完全可以只用設置這個值來保持長連接的.
客戶端在發(fā)送ping消息時服務端會相應的返回pong消息來進行回應.同時okhttp也實現(xiàn)了pong,服務端在發(fā)起ping的時候客戶端會通過pong來進行回應,即:在進行長連接時,客戶端不需要進行只需要服務端進行定時ping也是可以保持長連接的.
接下來就開始講和我們密切相關的readTimeout和writeTimeout了,當然也是最復雜的.其中最重要的還是readTimeout,我們先看writeTimeout
writeTimeout
這個值大致有3個地方用到

其中第二處和第三處的用用法是一致的,最后都是調用了
sink.timeout().timeout(writeTimeout, MILLISECONDS);
這寫到底是什么意思呢?
這個就不得不說okio了,okhttp中幾乎所有的流的操作都是由okio完成的,在okio.AsyncTimeout中對Sink(類似于OutputStream)和Source(類似于InputStream)進行了一層封裝


/**
Don't write more than 64 KiB of data at a time, give or take a segment. Otherwise slow
connections may suffer timeouts even when they're making (slow) progress. Without this, writing
a single 1 MiB buffer may never succeed on a sufficiently slow connection.
*/
private static final int TIMEOUT_WRITE_SIZE = 64 * 1024;
這其中的邏輯還是相當復雜的,大致意思就是所有的sink都被封裝了一個超時機制,需要在我們設置的時間內寫出TIMEOUT_WRITE_SIZE(64k)的數(shù)據(jù),如果無法完成即為超時,所以,我們在上次文件時明明只設置了幾十秒的超時時間卻不會超時.
在http2中就沒有再使用okio的超時機制了,當然超時計時器還是用的AsyncTimeout.的Watchdog








可以看到,在http2中采用的是線程等待的策略
readTimeout
readTimeout和writeTimeout幾乎完全一樣,只是操作相反,而且header的讀取和body的讀取是分開進行的,由于header數(shù)據(jù)量較小就不用討論了.
okio中每次讀取不大于8k.
final class Segment {
/** The size of all segments in bytes. */
static final int SIZE = 8192;


http2中每次讀取不大于8k.


然后還漏了一點:

socket.setSoTimeout(chain.readTimeoutMillis());
這行代碼什么意思呢?
setSotimeout(10000)是表示如果對方連接狀態(tài)10秒沒有收到數(shù)據(jù)的話強制斷開客戶端。
如果想要長連接的話,可以使用心跳包來通知服務器,也就是我沒有發(fā)給你數(shù)據(jù),但是我告訴你我還活著.
最后,如果超時時間設置的如果是0,那么代表超時時長為無限.
附上okhttp的默認超時時間

總結
到此這篇關于OkHttp的超時時間的文章就介紹到這了,更多相關OkHttp超時時間內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringMVC的組件之HandlerExceptionResolver詳解
這篇文章主要介紹了SpringMVC的組件之HandlerExceptionResolver詳解,不管是在處理請求映射(HandlerMapping),還是在請求被處理(Handler)時拋出的異常,DispatcherServlet都會委托給HandlerExceptionResolver進行異常處理,該接口只有一個方法,需要的朋友可以參考下2023-10-10
SpringMVC框架post提交數(shù)據(jù)庫出現(xiàn)亂碼解決方案
這篇文章主要介紹了SpringMVC框架post提交數(shù)據(jù)庫出現(xiàn)亂碼解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09

