当前位置: 代码迷 >> 综合 >> Android-抓包工具-(抓客户端)Fiddler(windows)/Carles(mac),还有抓服务端的,线程池
  详细解决方案

Android-抓包工具-(抓客户端)Fiddler(windows)/Carles(mac),还有抓服务端的,线程池

热度:87   发布时间:2023-11-25 12:59:04.0

原理

  1. 选择网络框架

Xutils、Volley、OkHttp、Retrofit

发送一个网络请求

  集成OkHttp

OkHttpClient client = new OkHttpClient(); // okhttp 配置一些默认参数
FormBody.Builder builder = new FormBody.Builder();
builder.add("key", "0f08cd674792667feb5ce236ea028747");

okhttp源码解析

来源 https://github.com/square/okhttp

OkHttpClient : 建议OkHttp的客户端,初始化OkHttp要使用的配置信息。

查看OkHttpClient 内部源码,其构造方法就是赋值作用,通过传入的builder值,赋值到OkHttpClient成员变量里。

Builder下:new了一个OkHttpClient里面有个Builder()给OkHttp设置一些参数

public Builder() {
//Dispatcher 相当于任务调度器dispatcher = new Dispatcher();
//协议protocols = DEFAULT_PROTOCOLS;
//网络是否加密connectionSpecs = DEFAULT_CONNECTION_SPECS;
//事件监听-通过工厂模式eventListenerFactory = EventListener.factory(EventListener.NONE);
//代理proxySelector = ProxySelector.getDefault();if (proxySelector == null) {proxySelector = new NullProxySelector();}
//设置cookiecookieJar = CookieJar.NO_COOKIES;
//socketFactory = SocketFactory.getDefault();
//host认证-跟https相关hostnameVerifier = OkHostnameVerifier.INSTANCE;certificatePinner = CertificatePinner.DEFAULT;proxyAuthenticator = Authenticator.NONE;authenticator = Authenticator.NONE;
//连接池connectionPool = new ConnectionPool();
//DNS解析dns = Dns.SYSTEM;
...
//连接时间connectTimeout = 10_000;
//读取时间readTimeout = 10_000;
//写入时间writeTimeout = 10_000;
}

 

 Dispatcher()管所有的任务,点击进入查看源码

拿到具体的请求数量;

public synchronized int getMaxRequests() {return maxRequests;}

拿到当前线程队列有哪些,具体管控哪些请求队列;

  void enqueue(AsyncCall call) {synchronized (this) {readyAsyncCalls.add(call);}promoteAndExecute();}

点击进入DEFAULT_PROTOCOLS 协议,http网络,点击DEFAULT_CONNECTION_SPECS,https网络

点击MODERN_TLS 进入,TLS加密解密有哪些版本

点击APPROVED_CIPHER_SUITES进入,TLS所有版本

// This is nearly equal to the cipher suites supported in Chrome 51, current as of 2016-05-25.// All of these suites are available on Android 7.0; earlier releases support a subset of these// suites. https://github.com/square/okhttp/issues/1972private static final CipherSuite[] APPROVED_CIPHER_SUITES = new CipherSuite[] {// TLSv1.3CipherSuite.TLS_AES_128_GCM_SHA256,CipherSuite.TLS_AES_256_GCM_SHA384,CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
...
...
}

点击ConnectionSpec.CLEARTEXT进入:没有进行https加密,默认支持http请求

 

Request:请求信息封装

Request request = new Request.Builder().url("http://apis.juhe.cn/lottery/types").post(builder.build()).build(); //建造者设计模式,优点:实现圆点(连点)操作

 点击查看这里面的Builder(),返回url是Builder本身,可以实现灵敏操作

Call call = client.newCall(request);

点击newCall()方法

这个Call面向抽象编程

Call:可执行异步或者同步请求

实际上调用的是这个RealCall,

来执行网络请求

//Response execute = call.execute();  //同步请求可直接拿到Response//基于观察者模式拿到responsecall.enqueue(new Callback() { //异步请求@Overridepublic void onFailure(Call call, IOException e) {Log.e("initGetNetData","onFailure" + e);}@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.e("initGetNetData","onResponse" + response.body().string());}});

 同步方法synchronized (this)

这里的client就是OkHttpClient,它构造了一个类似于任务管理器dispatcher()去执行了一个enqueue()方法,并传入到匿名内部类(观察者模式-数据回调的接口Callback responseCallback,传递到Asyncall()对象里)

点击AsyncCall()进入:它实际上就是个Runnable,Runnable可以放到Handler里面,执行相应的代码

点击enquene进入:就回到之前提到过的

点击promoteAndExecute进来:

点击executeOn进入:也是RealCall里面的内部类

 

点击executorService()进入:executorService就是一个线程池,把任务调度器,把创建好的线程池,传入到executeOn()里面。

Handler可以执行Runnable

线程池也可以执行Runnable

复写Runnable的重要方法—NamedRunnable

Run()里面是一个具体想要的一个网络请求

通过Runnable把它加入到线程池里,线程池通过它的线程管理去执行Runnable对象,这样就可以走到Run()方法,这里面用了了个抽象方法,可以由具体的类(如:这里的AsyncCall)调用去实现(重写execute())

同样在RealCall下,这段代码是实现OkHttp的核心

拦截器

“U”型处理,即向下跑完代码,再向上走

  1. Interceptor:  OkHttp中的精华就是 拦截器,责任链设计模式
  2. RetryAndFollowUpInterceptor:负责错误重试及重定向。                                                                                                             比如发送一个请求失败了,它可以进行一个错误的重试还可以进行重定向
  3. BridgeInterceptor:负责组装请求及解析数据。                                                                                                                               一个是Request负责组装还有一个Response负责解析
  4. CacheInterceptor:负责读取缓存和更新缓存。                                                                                                                               发送一个网络请求,可以读取这个缓存,响应速度更快,然后请求下来的数据(最新的),那这个缓存拿回来的Response是最新数据,需更新本地缓存。
  5. ConnectInterceptor:负责和服务器建立连接。
  6. CallServerInterceptor:负责发送请求及接收数据, Okio 对接                                                                                                            OkHttp当中最重要的一个拦截器,点击CallServerInterceptor进入:面向抽象编程,指定一个实体对象来做的

定位HttpCodec源码

public final class Http1Codec implements HttpCodec {private static final int STATE_IDLE = 0; // Idle connections are ready to write request headers.
...
/** The client that configures this stream. May be null for HTTPS proxy tunnels. */final OkHttpClient client;
/** The stream allocation that owns this stream. May be null for HTTPS proxy tunnels. */final StreamAllocation streamAllocation;
...final BufferedSource source;final BufferedSink sink; //相当于一个流
...
}

OkHttp基于Okio(IO数据流,Okio封装在OkHtto里面),所以Okio是具体负责和服务端数字缔结的,它也是基于socket连接,读取相应数据

java除了IO,还有一个NIO,也是流操作

OkHttp相对于客户端,它封装的代码组装Request,拿到Response,,具体的网络请求和服务端对接的,就是CallServerInterceptorl里面的HttpCodec,调用相应的Okio里面的代码

同步请求与异步请求

拦截器可以处理Request封装请求,还可以拿到Response

如:统一给Request加一些统一的参数,每个接口同样的参数,那就可以单独做一个拦截器往里添加

如果对Response做一些统一处理,比如错误码处理,可定义一个拦截器,放到client里去处理。

 

Get请求

从指定的资源请求数据。

GET 请求不应在处理敏感数据时使用

GET 请求有长度限制

例子:http://v.juhe.cn/joke/content/list.php?key=您申请的KEY&page=2&pagesize=10&sort=asc&time=1418745237

把参数拼接成url,发送到服务器

/ :目录

?:分割前面的url和后面的参数

这些参数是Key和Value一一对应的,key是写死的,value可以想传什么值就传什么值

Post请求

post请求是放到http这个FormBody里面,通过抓包Contents目录下查找到key,通常来讲Post请求更安全一些

上传文件,像指定的服务器推送数据(把key推送到服务端),服务端也相应的给客户端Response(请求到的一些资源)

现在大多数app接口都不用get,都用post,post 既能向服务端发送数据(包括大文件),也可以进行请求数据(安全性更高,对数据格式长度没有限制,get是有长度限制的)

有抽象类,就有对应的实体类

点进去FormBodyMultipartBody,都是用于post请求的

FormBody属于普通请求,其CONTENT_TYPE = MediaType.get("application/x-www-form-urlencoded")

MultipartBody属于上传文件的(图片,视频,文档),它的CONTENT_TYPE是

参考 https://imququ.com/post/four-ways-to-post-data-in-http.html

FormBody.Builder builder = new FormBody.Builder();builder.add("key", "0f08cd674792667feb5ce236ea028747");Request request = new Request.Builder().url("http://apis.juhe.cn/lottery/types").post(builder.build()).build(); //建造者设计模式,优点:实现圆点(连点)操作Call call = client.newCall(request);//Response execute = call.execute();  //同步请求可直接拿到Response//基于观察者模式拿到responsecall.enqueue(new Callback() { //异步请求@Overridepublic void onFailure(Call call, IOException e) {Log.e("initGetNetData","onFailure" + e);}@Overridepublic void onResponse(Call call, Response response) throws IOException {Log.e("initGetNetData","onResponse" + response.body().string());}});

 

 

  相关解决方案