Android OkHttp官方Wiki之Connections

雖然用戶只使用URL發起請求時,但是OkHttp會使用URL,Address和Route路由來與服務器進行連接。

URLs

URL統一資源標識符是用來連接HTTP和互聯網的最基本的要素。URL除了爲網絡上的所有東西提供一個通用,分散的命名方案,同時也能指定如何訪問網絡資源。一個URL的組成成分包括了Scheme方案,Username and Password,Host主機名,Port端口,Path路徑,Query查詢參數,Fragment片段。

URLs是抽象的:

  • URL可以指定請求是純文本的(http)或者加密的(https),但是不需要使用哪種加密算法。它們也沒有指定如何驗證對等的證書(HostnameVerifier)或者哪些證書可以被信任(SSLSocketFactory)。
  • URL沒有指定是否應該使用特定的代理服務器或者如何使用該代理服務器進行身份驗證。
  • 同時URLs也是具體的:每一個URL標識一個特定的路徑(如/square/okhttp)和查詢(如q=sharks&lang=en)。每一個Web服務器都有許多URL。

    在OkHttp中使用HttpUrl這個類來表示統一資源表示符Url,可以使用這個類來組合和分解Internet地址。

    public final class HttpUrl
    extends Object

    例如下面的代碼會組合並打印一個Google Search的URL:

    
       HttpUrl url = new HttpUrl.Builder()
           .scheme("https")
           .host("www.google.com")
           .addPathSegment("search")
           .addQueryParameter("q", "polar bears")
           .build();
       System.out.println(url);

    打印結果如下:
    https://www.google.com/search?q=polar%20bears

    下面的代碼會打印Twitter search URL中人類可讀的查詢參數:

       HttpUrl url = HttpUrl.parse("https://twitter.com/search?q=cute%20%23puppies&f=images");
       for (int i = 0, size = url.querySize(); i < size; i++) {
         System.out.println(url.queryParameterName(i) + ": " + url.queryParameterValue(i));
       }

    打印結果如下:
    q: cute #puppies
    f: images

    除了可以將組成成分組合成URL和將URL分解爲個組成成分,HttpUrl這個類還可以實現對URL的爬取解析,例如通過單擊指定頁面上的一個相對鏈接,將獲得什麼地址。例如下面的代碼:

      HttpUrl base = HttpUrl.parse("https://www.youtube.com/user/WatchTheDaily/videos");
       HttpUrl link = base.resolve("../../watch?v=cbP2N1BQdYc");
       System.out.println(link);

    打印結果如下:
    https://www.youtube.com/watch?v=cbP2N1BQdYc

    Addresses

    一個地址指定Web服務器(例如github.com)以及連接到該服務器所需的所有靜態配置:端口數量,HTTPS設置和首選的網絡協議(例如HTTP/2或者SPDY)。

    共享相同地址的url可能共享相同的TCP套接字連接。共享連接具有顯著的性能優勢: 更低的延遲,更高的吞吐量(得益於TCP慢啓動)和保護電池。OKHttp使用ConnectionPool來自動複用HTTP/1.X連接和多路複用HTTP/2和SPDY連接。

    在OkHttp中,地址的某些字段來自於URL(scheme,主機名,端口),其餘部分則來自OkHttpClient。

    在OkHttp中Address類如下:

    public final class Address
    extends Object

    Address是一個連接到服務器的規範。對於一些簡單的連接,這是服務器的主機名和端口。如果請求一個顯式的代理(或者沒有明確請求代理),那麼這也包括代理信息。對於安全連接,地址還包括SSL套接字工廠,主機名驗證器和證書pinner。

    Routes

    路由提供了必要的動態信息,以便連接到網絡Web服務器。這包含了嘗試連接的特定IP低着(通過DNS查詢發現),要使用的確切代理服務器(如果使用了ProxySelector),以及要協商的TLS版本(用於HTTPS連接)。
    對於一個地址來說可能有很多網絡路徑可以到達。例如,託管在多個數據中心中的Web服務器可能會在其DNS響應中產生多個不同的IP地址。

    Connections

    當使用OkHttp來請求一個URL地址時,會做如下步驟:

  • 1.OkHttp使用URL和已經配置好的OkHttpClient來創建一個地址。這個地址指定了我們如何連接到Web服務器。
  • 2.OkHttp嘗試從連接池中檢索該地址的連接。
  • 3.如果在連接池中沒有檢索到該地址的連接,那麼OkHttp將嘗試選擇一條路由路徑,即發出一個DNS請求來獲取服務器的IP地址。然後在必要時選擇一個TLS版本和代理服務器。
  • 4.如果這是一條新的路由,OkHttp將通過構建一個直接的套接字連接,一個TLS隧道(用於HTTP代理上的HTTPS)或者直接的TLS連接來連接。根據需要,OkHttp會進行TLS握手。
  • 5.跟服務器連接完成後,OkHttp會發送HTTP請求並讀取響應結果。
  • 如果連接存在問題,OkHttp將選擇另一條路由路徑並再次嘗試。當服務器地址的子集不可到達時,OkHttp允許恢復。這對於連接失敗或者TLS版本不支持時,這很有用。
    一旦接收到響應結果,此次連接將被返回到連接池中以便在將來的請求中可以重用它。當連接池中的某個連接在一段時間內不使用時,該連接便從連接池中被丟棄出去。

    在OkHttp中,Connection是一個接口:

    public interface Connection

    Connection是一個HTTP,HTTPS或者HTTPS+HTTP/2連接的套接字和流,可以用於多個HTTP請求/響應交換。連接可以直接連接到源服務器或者通過代理連接。這個類的典型實例是由HTTP客戶機自動創建,連接和執行的。應用程序可以使用這個類作爲連接池的成員來監視HTTP連接。

    參考資料:
    https://github.com/square/okhttp/wiki/Connections
    http://square.github.io/okhttp/3.x/okhttp/okhttp3/HttpUrl.html
    http://square.github.io/okhttp/3.x/okhttp/okhttp3/Address.html

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章