Cronet是什么?
From chatgpt
Cronet(Chromium Network Stack)是Google Chrome浏览器的网络堆栈的开源版本,用于处理网络请求和响应。它是一个用于Android平台的网络库,提供了高性能的网络功能,包括HTTP请求、数据下载、WebSocket支持等。Cronet的目标是为Android应用程序提供高效、可靠和安全的网络通信能力。
以下是Cronet的一些特点和功能:
- 性能优化: Cronet旨在提供高性能的网络通信,通过多线程处理和异步操作来最大程度地减少网络延迟。
- HTTP/2支持: Cronet支持HTTP/2,这是一种现代的、高效的HTTP协议,可以加快页面加载速度并减少网络资源的浪费。
- 安全性: Cronet支持HTTPS,可以确保数据在传输过程中的加密和安全性。
- Quic支持: Cronet还支持QUIC协议,这是Google开发的一种基于UDP的传输协议,旨在提供更低的延迟和更高的性能。
- WebSocket支持: Cronet可以用于处理WebSocket连接,使应用程序可以进行实时双向通信。
- 缓存管理: Cronet可以自动管理缓存,以提高资源的重复利用率,并减少不必要的网络请求。
- 可配置性: Cronet允许开发人员配置各种网络参数,以满足应用程序的需求。
Cronet最初是为Chrome浏览器的Android版本开发的,但后来被开源并提供给其他Android应用程序开发人员使用。它为开发人员提供了更多灵活性和控制,使他们能够更好地管理应用程序的网络通信,同时受益于Google Chrome团队的网络优化经验。
需要注意的是,Cronet在不同版本中可能会有一些变化和改进,因此在使用时应查阅官方文档以获取最新的信息和指南。
Chromium-net是什么?
From chatgpt
Chromium Net(简称Chromium网络)是Chromium项目的一部分,用于处理网络通信的底层组件。Chromium是一个开源项目,它是Google Chrome浏览器的基础,因此Chromium Net在Chrome浏览器中用于处理网络请求和响应。
以下是Chromium Net的一些主要特点和功能:
- 网络协议支持: Chromium Net支持各种网络协议,包括HTTP、HTTPS、HTTP/2、QUIC(Quick UDP Internet Connections)等。这使得Chrome浏览器能够与Web服务器进行高效的通信,并利用现代网络协议提供更快的页面加载速度和更好的性能。
- 网络安全性: Chromium Net负责处理HTTPS通信,确保通过SSL/TLS加密传输的数据的安全性。它还实施了一系列的安全策略和机制,用于保护用户免受网络攻击和恶意网站的威胁。
- 代理支持: 该组件允许配置代理服务器,以允许网络请求通过代理服务器进行中转,从而实现更高级的网络控制和隐私保护。
- 流量管理: Chromium Net可以帮助浏览器管理网络流量,包括请求和响应的缓存、重定向、流量控制等。
- 数据压缩: 它支持数据压缩,以减少传输的数据量,提高网络性能。
- HTTP缓存: Chromium Net包括HTTP缓存管理,以在本地存储和管理已下载的资源,以减少重复下载和提高页面加载速度。
Chromium Net是Chromium项目中的一个关键组件,它使得Chrome浏览器能够在各种网络条件下提供出色的性能和安全性。除了在Chrome浏览器中使用外,Chromium Net的一些部分也可以在其他项目中使用,以处理网络通信。它的开源性质使得开发人员可以查看其源代码并进行自定义,以满足特定需求。需要注意的是,Chromium Net是一个复杂的网络堆栈,需要深入的专业知识来理解和配置。
如何使用Cronet发起请求
Cronet提供两种发起请求的方式,异步和同步。
val requestBuilder = cronetEngine.newUrlRequestBuilder(url, callback, executorService)
requestBuilder.build().start()
2. ### 同步
val connection = engine.openConnection(url)
URL.setURLStreamHandlerFactory(engine.createURLStreamHandlerFactory())
跟代码
本文将跟着异步调用的方式跟着代码看网络请求大致流程,所以我们跟代码的入口是:
1 | csharp复制代码CronetUrlRequest.start() |
从上面的流程可以看到,java 层就是纯粹的包装层,C++层的入口是 cronet_url_request.cc#start(),那我们直接去看这个文件。
1 | less复制代码//cronet_url_request.cc |
实际上逻辑是在 NetworkTasks 中
1 | rust复制代码//CronetRequest::NetworkTasks |
从上面这个函数体来看,cronet 的 C++ 层代码跑到这里基本流程就结束了,后续流程嫁接进 chromuim-net 模块了,先通过 url_request_context 构造 url_request,再调用 url_request 的 Start() 方法发起请求。
构造 url_request
1 | csharp复制代码//net/url_request/url_request_context.cc |
调用 url_request 的 Start() 函数进入 chromium-net 的核心网络请求流程。
1 | scss复制代码//net/url_request/url_request.cc |
StartJob(context_->job_factory()->CreateJob(this))
这一句核心代码包含两个元素,一个是通过 URLRequestJobFactory 构造一个 URLRequestJob,然后 startJob,这两个类所在的文件是:
- net/url_request/url_request_job_factory.h
- net/url_request/url_request_job.h
在继续往底下深入看之前,用我们自己的思路大概猜一下,URLRequestJob 是单个网络请求任务的包装类,内部包含着各个阶段的流转,而 URLRequest 是 job 的外观类。我们继续看 StartJob 函数:
1 | scss复制代码//net/url_request/url_request.cc |
这里可以看到,当 URLRequestJob
start
后,URLRequest
的状态变成了 ERR_IO_PENDING
,这是 chromium-net
里到处都能见到的状态机流转来实现异步等待的方式,有许多地方设置状态,状态机收到状态后做相应的响应,ERR_IO_PENDING
的状态说明当前线程已经 pending
了,需要等待 IO 线程执行完任务后解除 pending 状态。
那我们继续往下看,目前跟到了 URLRequestJob 的 start 方法了
1 | csharp复制代码// net/url_request/url_request_job.h |
URLRequestJob::Start()方法是个虚方法,是由子类实现具体的方法体的,因为我们重点关注 http 的请求,所以 直接去 url_request_http_job 里看 http 协议相关实现即可
直接看 Start() 方法
1 | scss复制代码//net/url_request/url_request_http_job.cc |
那我们继续看 HttpNetworkTransaction 的 Start() 入口
1 | scss复制代码//net/http/http_network_transaction.cc |
这里出现了上面我们说过的状态机,通过设置 next_state_(即下一步动作), DoLoop 转动状态轮盘,执行下一步任务,这里下一步的状态是准备创建 stream,stream 是请求流,可以理解为服务器和客户端 TCP 连接内用于交换帧数据的独立双向序列,如果协议是 http1.0,那么一个 TCP 连接只有一个 stream,如果是 http2,由于多路复用的特性,多个 stream 可以共用一个 TCP 连接。 既然这里已经走到了创建 stream 的状态了,大概也可以猜到,网络请求的状态流转就是依赖HttpNetworkTransaction 中的状态机,这有点像是 OKHttp 中的 InterceptorChain,一个是通过状态流转,一个是链式推进,那我们看看 HttpNetworkTransaction::DoLoop 函数究竟长啥样。
1 | ini复制代码//net/http/http_network_transaction.cc |
从上面代码中,我们可以看到,HttpNetworkTransaction 中的状态机从初始的STATE_NOTIFY_BEFORE_CREATE_STREAM 状态开始轮转,逐个状态往下推进,最终完成了整个网络请求。代码中的每个状态在代码中的顺序,就是一个普通网络请求的生命周期,上一个状态执行完后,只要不是 IO_PENDING,在 Doxxx 中总会指定下一状态,并且继续 loop,从而执行下一状态的对应工作。
总结
我们的这一期分享中,并没有深入细节,只是从比较高的视野去看整体的流程,后续会继续深入细节处,分享更加细节的chromium-net相关知识点,包括但不仅限于:
- socket pool 和 OKHttp 的ConnectionPool 异同
- cache 控制
- 设计模式
- …
受限于本人有限的水平,文中必然有描述错误或者理解错误的地方,如看到请指正。
你可能感兴趣
Android QUIC 实践 - 基于 OKHttp 扩展出 Cronet 拦截器 - 掘金 (juejin.cn)
Android启动优化实践 - 秒开率从17%提升至75% - 掘金 (juejin.cn)
如何科学的进行Android包体积优化 - 掘金 (juejin.cn)
Android稳定性:Looper兜底框架实现线上容灾(二) - 掘金 (juejin.cn)
基于 Booster ASM API的配置化 hook 方案封装 - 掘金 (juejin.cn)
记 AndroidStudio Tracer工具导致的编译失败 - 掘金 (juejin.cn)
Android 启动优化案例-WebView非预期初始化排查 - 掘金 (juejin.cn)
chromium-net - 跟随 Cronet 的脚步探索大致流程(1) - 掘金 (juejin.cn)
Android稳定性:可远程配置化的Looper兜底框架 - 掘金 (juejin.cn)
一类有趣的无限缓存OOM现象 - 掘金 (juejin.cn)
Android - 一种新奇的冷启动速度优化思路(Fragment极度懒加载 + Layout子线程预加载) - 掘金 (juejin.cn)
Android - 彻底消灭OOM的实战经验分享(千分之1.5 -> 万分之0.2) - 掘金 (juejin.cn)
本文转载自: 掘金