5

移动端(android、ios)接入cronet实践 | iTimeTraveler

 3 years ago
source link: https://itimetraveler.github.io/2019/07/25/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%8E%A5%E5%85%A5Cronet%E7%BD%91%E7%BB%9C%E5%BA%93%E5%AE%9E%E8%B7%B5/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

移动端(Android、iOS)接入Cronet实践

QUIC协议

QUIC, a multiplexed stream transport over UDP 是Chromium使用的通信协议,是基于UDP实现的类似于 TCP+TLS+HTTP/2 的协议。也是HTTP 3.0的设计方案。有兴趣的话大家可参考文档: Playing with QUIC

Chromium项目是开源的,The Chromium Projects(http://dev.chromium.org/chromium-projects) 文档详细介绍了Chromium项目的实现原理,以及如何获取源码并进行编译。

Cronet 库是Chrome使用的移动端网络库。支持 HTTP、HTTP/2 以及 QUIC 协议。支持 Android 和 iOS 平台。 其编译工具是 gn 和 ninja,类似于 cmake 与 make 的关系。 下面介绍 Cronet 库的编译及编译注意事项。

获取Chromium源码

可以参考官方文档:Checking out and building Chromium for Mac

获取源码之前,首先需要下载安装 depot_tools 工具。在一个适当的目录下clone depot_tools包:

$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

depot_tools的路径(最好是绝对路径,~需替换为$HOME)加进环境变量PATH中,假设 depot_tools 工程在/path/to/depot_tools目录下:

export PATH=$PATH:/path/to/depot_tools

如果从来没有下载过Chromium的代码的话,为源码创建一个文件夹并下载源码:

mkdir chromium && cd chromium
fetch --no-history chromium # 可能花费30min或几小时,依网络速度而不同

–no-history 可以节省代码下载时间,它忽略仓库的历史信息;整个代码量较大,约 14G,且需要翻墙,1M 左右的速度需要 20~30 分钟。若中间拉取失败,可以执行 gclient sync 继续拉取, 拉取结束后,该目录会生成一个 src 目录,包含 cronet 源码。

获取源码是很漫长的过程,Chromium项目的源码有8G。我花了2个半小时才完成。中途遇到了download_from_google_storage.py 下载文件没反应的问题,参考了Chromium的源码获取与编译(2018-06-06)

最终chromium/src代码大小如下:

$ du -d 1 -h | sort -h
48K ./google_update
56K ./build_overrides
184K ./apps
208K ./styleguide
420K ./gin
424K ./rlz
480K ./cloud_print
540K ./crypto
564K ./jingle
596K ./infra
632K ./dbus
684K ./sql
876K ./printing
916K ./fuchsia
916K ./url
1.0M ./ipc
1.0M ./pdf
1.1M ./skia
2.1M ./google_apis
3.4M ./storage
3.7M ./sandbox
5.0M ./courgette
6.2M ./build
6.5M ./headless
7.4M ./chromecast
7.8M ./android_webview
7.8M ./mojo
9.2M ./device
9.2M ./testing
10M ./docs
12M ./cc
13M ./ppapi
15M ./gpu
17M ./chromeos
18M ./services
19M ./remoting
20M ./extensions
22M ./base
27M ./ash
41M ./native_client_sdk
49M ./ios
75M ./ui
78M ./buildtools
80M ./media
94M ./content
98M ./out
112M ./net
158M ./tools
295M ./components
737M ./v8
784M ./chrome
1007M ./.git
2.0G ./native_client
13G ./third_party
19G .

命令行翻墙,需要使用 http proxy 配置:

export http_proxy=http://127.0.0.1:8118 
export https_proxy=http://127.0.0.1:8118

// git代理,我没有使用
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

启动 privoxy 转换 socks5 为 http proxy:

privoxy --no-daemon /usr/local/etc/privoxy/config

编译Cronet

Cronet的源码位于 src/components/cronet 目录,官方编译流程可参考Cronet build instructions,编译环境要求:

  • Linux:python 2.7.5,及 jdk 8,较高版本由于接口不兼容需避免使用。
  • Mac: python 2.7.5,jdk 8,以及 xcode。 进入 chromium/src 目录,执行下面命令

Android / iOS builds

$ ./components/cronet/tools/cr_cronet.py gn --out_dir=out/Cronet   # 生成 ninja 文件

如果主机是linux,build的是Android的库。如果主机是MacOS,build的是ios库。以下命令在Mac上会生成 cronet 静态库,目录 obj/components/cronet/ios/libcronet*.a

Desktop builds (targets the current OS)

gn gen out/Cronet

Running the ninja files

输入 ninja 文件执行编译,必须指定为 cronet_package

$ ninja -C out/Cronet cronet_package

这个命令会编译 cronet 模块,及其依赖的所有模块,包括base,crypto,boringssl,protobuf,url等。编译Cronet库,最终文件可以在out/Cronet/cornet中寻找。

生成的文件

iOS 库:

  • out/MyCronet/obj/components/cronet/ios/libcronet.a, 大小为 89M;
  • out/MyCronet/obj/components/cronet/ios/libcronet_static.a, 大小为 17M;
  • out/MyCronet/obj/components/cronet/ios/libcronet_deps_complete.a,大小为 1G。

Android 库:

  • out/Cronet-android/lib.java/components/cronet/android/ 所有 jar 包在此目录下,一般不用;
  • out/Cronet-android/cronet/ 需要使用cronet库的java API的so、及jar包都在此目录下
  • out/Cronet-android/libcronet.77.0.3825.0.so,strip 后的库,6M;
  • out/Cronet-android/lib.unstripped,未 strip 的库在此目录下。50.9M;
  • out/Cronet-android/gen/components/cronet/android/cronet_jni_registration.h,该文件便是自动生成的JNI头文件

使用Cronet

Debug Log

C++层的日志可以通过 adb logcat 输出. 但是默认只显示 FATAL 级别的日志。如果想要更改日志输出级别,可以通过以下命令打开chromium日志输出:

See VLOG(1) and VLOG(2) logging:

$ adb shell setprop log.tag.CronetUrlRequestContext VERBOSE

See VLOG(1) logging:

$ adb shell setprop log.tag.CronetUrlRequestContext DEBUG

See NO (only FATAL) logging:

$ adb shell setprop log.tag.CronetUrlRequestContext NONE

Network Log

NetLog 是 Chromium 网络模块的日志:NetLog: Chrome’s network logging system。可以使用下面两行代码操作 dump 出 chromium 网络模块的日志:

CronetEngine.startNetLogToFile()
CronetEngine.stopNetLog()

Chromium网络模块的日志输出内容是 JSON 格式的,所以需要主动调用 stopNetLog() 方法保证 JSON日志的完整性。

导出的log文件可以使用 https://netlog-viewer.appspot.com/#import 分析。如果打不开,可以使用 Chromium NetLog dump viewer 这个Chrome扩展程序。

参考 GN Quick Start guideGN Language and Operation,建议大家先了解下target的概念,因为gn命令操作的基本上都是target。

// 列出指定构建目录下所有的targets
$ gn ls out/Default

// 查看当前环境的配置参数
$ gn args --list out/Default

// 显示关于一个给定target或config的信息。
// usage: gn desc <out_dir> <label or pattern> [<what to show>] [--blame] [--format=json]
$ gn desc out/Default net

// 查找两个taregets之间的依赖路径
$ gn path out/Default //base //net --all

// 查找反向的依赖(也就是依赖此target的其他targets)
$ gn refs out/Default/ //net

// 检查头文件依赖的有效性
$ gn check out/Default/ //net

Cronet request lifecycle

The Cronet request lifecycle

$ ninja -help
usage: ninja [options] [targets...]

if targets are unspecified, builds the 'default' target (see manual).

options:
--version print ninja version ("1.8.2")

-C DIR change to DIR before doing anything else
-f FILE specify input build file [default=build.ninja]

-j N run N jobs in parallel [default=6, derived from CPUs available]
-k N keep going until N jobs fail [default=1]
-l N do not start new jobs if the load average is greater than N
-n dry run (don't run commands but act like they succeeded)
-v show all command lines while building

-d MODE enable debugging (use -d list to list modes)
-t TOOL run a subtool (use -t list to list subtools)
terminates toplevel options; further flags are passed to the tool
-w FLAG adjust warnings (use -w list to list warnings)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK