OkHttp3.14 源码剖析系列(五)——路由选择机制

个人博客:https://blog.N0tExpectErr0r.cn

小专栏:https://xiaozhuanlan.com/N0tExpectErr0r

系列索引

本系列文章基于 OkHttp3.14

OkHttp3.14 源码剖析系列(一)——请求的发起及拦截器机制概述

OkHttp3.14 源码剖析系列(二)——拦截器大体流程分析

OkHttp3.14 源码剖析系列(三)——缓存机制分析

OkHttp3.14 源码剖析系列(四)——连接的建立概述

OkHttp3.14 源码剖析系列(五)——路由选择机制

OkHttp3.14 源码剖析系列(六)——连接复用机制及连接的建立

OkHttp3.14 源码剖析系列(七)——请求的发起及响应的读取

路由选择

当我们第一次尝试从连接池获取连接获取不到时,若检查发现路由选择器中没有可供选择的路由,首先会进行一次路由选择的过程,因为 HTTP 请求的过程中,需要先找到一个可用的路由,再根据代理协议规则与目标建立 TCP 连接。

Route

我们先了解一下 OkHttp 中的 Route 类:

public final class Route {
   
    final Address address;
    final Proxy proxy;
    final InetSocketAddress inetSocketAddress;
    // ...
}

它是一个用于描述一条路由的类,主要通过了代理服务器信息 proxy、连接目标地址 InetSocketAddress 来描述一条路由。由于代理协议不同,这里 InetSocketAddress 会有不同的含义:

  • 没有代理的情况下它包含的信息是经过了 DNS 解析的 IP 以及协议的端口号
  • SOCKS 代理的情况下,它包含了 HTTP 服务器的域名和协议端口号
  • HTTP 代理的情况下,它包含了代理服务器经过了 DNS 解析的 IP 地址及端口号

Proxy

接着我们了解一下 Proxy 类,它是由 Java 原生提供的:

public class Proxy {
   
    public enum Type {
   
        // 表示不使用代理
        DIRECT,
        // HTTP代理
        HTTP,
        // SOCKS代理
        SOCKS
    };
    private Type type;
    private SocketAddress sa;
    // ...
}

它是一个用于描述代理服务器的类,主要包含了代理协议的类型以及代理服务器对应的 SocketAddress 类,有以下三种类型:

  • DIRECT:不使用代理
  • HTTP:HTTP 代理
  • SOCKS:SOCKS 代理

RouteSelector

在代码中是通过 RouteSelector.next 方法进行的路由选择的过程,RouteSelecter 是一个负责负责管理路由信息,并辅助选择路由的类。它主要有三个职责:

  1. 收集可用的路由
  2. 选择可用的路由
  3. 维护连接失败路由信息

下面我们对它的三个职责的实现分别进行介绍。

代理的收集

代理的收集过程在 RouteSelector 的构造函数中实现,RouteSelector 在创建 ExchangeFinder 时创建:

RouteSelector(Address address, RouteDatabase routeDatabase, Call call,
              EventListener eventListener) {
   
    this.address = address;
    this.routeDatabase = routeDatabase;
    this.call = call;
    this.eventListener = eventListener;
    resetNextProxy(address.url(), address.proxy());
}

让我们看到 resetNextProxy 方法:

/**
 * Prepares the proxy servers to try.
 */
private void resetNextProxy(HttpUrl url, Proxy proxy) {
   
    if (proxy != null) {
   
        // 若用户有设定代理,使用用户设置的代理
        proxies = Collections.singletonList(proxy);
    } else {
   
        // 借助ProxySelector获取代理列表
        List<Proxy> proxiesOrNull = address.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值