iOS 集成 Cronet 方法和测试

一、如何得到 Cronet 编译包

源码编译

可以参考 google 官方的指南 来编译。但编译过程非常坎坷,一路下来会遇到非常多的错误。不建议使用这种方式

使用编译好的

Google Cloud

谷歌在 Google Cloud 提供了编译好的包,编译周期非常短,基本上每天都有新包。选取指定的版本号下载即可。

gsutil

下载需要 gsutil 工具,可通过下面的方法来安装

复制代码
pip3 install gsutil

选择合适的版本

通过浏览版本记录,最新的版本是 2023.6.8 编译的 116.0.5820.0

Debug的就不用说了,肯定不能用到线上。

  • Release-iphonesimultor:intel芯片x86_64模拟器包

  • Release-m1 simulator:M1芯片模拟器+真机包

    不建议使用此包,目前公司还有同学在使用 intel 芯片开发,如果使用包含M1芯片的包,会导致项目编译不通过。

继续往前寻找,我们发现 2023.6.16 编译的 114.0.5735.140

  • Release-iphonesimultor:intel芯片x86_64模拟器包
  • Release-iphoneos:真机包

上面两个Release版本包,正是我们需要的。

下载包

我们使用 gsutil 工具来下载 114.0.5735.140 版本包。在终端执行如下命令即可

bash 复制代码
gsutil -m cp -r \
  "gs://chromium-cronet/ios/114.0.5735.140/Debug-iphonesimulator" \
  "gs://chromium-cronet/ios/114.0.5735.140/Debug-m1simulator" \
  "gs://chromium-cronet/ios/114.0.5735.140/Release-iphoneos" \
  "gs://chromium-cronet/ios/114.0.5735.140/Release-iphonesimulator" \
  "gs://chromium-cronet/ios/114.0.5735.140/Release-m1simulator" \
  .

合并包

通过 lipo 命令 来合并 Release-iphonesimulator 和 Release-iphoneos 两个包,打包成一个同时包含 arm64x86_64的包。可以使用静态包,也可以使用动态包。

lua 复制代码
lipo -create xxxx yyy -output Cronet

合并完之后,通过 file或者lipo -info命令查看包的架构

二、如何集成

新建好项目,将 Cronet.framework 添加到项目中,为什么能成功编译云清起来,还需要将一些依赖的系统库添加到项目中。

Github开源demo:github.com/lyandy/ios_...

三、API实践

Cronet采用NSURLProtocol切面编程的方式拦截了iOS系统的网络请求,集成起来相对容易。

设置Cronet

objectivec 复制代码
// 设置 支持 HTTP2, 如果设置为 NO,如果协议不支持H3,会降级到H1.1
    [Cronet setHttp2Enabled:YES];
    // 设置支持 QUIC
    [Cronet setQuicEnabled:YES];
    // 设置支持 Br 压缩算法,并列的有gzip算法
    [Cronet setBrotliEnabled:YES];
    // 设置 AcceptLanguages,AFN会自动补全设置,建议不单独设置
//    [Cronet setAcceptLanguages:@"en-US,en"];

    // 设置 请求的 UserAgent, AFN会自动补全设置,建议不单独设置
    // 这是设置生效顺序 URLRequest > Cronet > 默认
    // [Cronet setUserAgent:@"Dummy/1.0" partial:NO];

    // 设置 HTTP Cache 类型,建议不手动指定
//    [Cronet setHttpCacheType:CRNHttpCacheTypeDisabled];
    
    // 开启 metric 性能统计
    [Cronet setMetricsEnabled:YES];
    
    // 预先告诉 Cronet,支持 H3 的域名,以便尽快链接H3协议
    [Cronet addQuicHint:@"h2o.examp1e.net" port:443 altPort:443];

    // 开始cronet
    [Cronet start];

    // 建议不开启,开启后也会拦截所有的 NSURLConnection
    // 开启后,也会对webkit加载进行拦截。
//    [Cronet registerHttpProtocolHandler];

    // 是否要使用 Cronet 拦截指定请求
    // 不写的话,会拦截所有请求。最好是根据自己的条件来拦截
    [Cronet setRequestFilterBlock:^BOOL(NSURLRequest* request) {
        return YES;
    }];

hook 网络请求

下面是一个最简单的例子

ini 复制代码
- (void)startNSURLSession {
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    [Cronet installIntoSessionConfiguration:config]; // hook Protocol
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[@"https://h2o.examp1e.net?t=" stringByAppendingString:@([[NSDate date] timeIntervalSince1970]).stringValue]]];
    request.assumesHTTP3Capable = NO; // 关闭Apple QUIC
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *resp, __unused NSError *err) {
        NSLog(@"");
    }];
    
    [task resume];
}

四、测试

通过Charles抓包和Wireshark网络层转包来检测Cronet是否生效。

(以下演示结果均是使用 Github开源demo:github.com/lyandy/ios_... 的实验结果)

观察链接:h2o.examp1e.net?t=xxx (此链接支持H3,xxx是时间戳,防止出现LocalNetwork,H3自动降级为H2)

Charles

为了观察效果,我们故意设置Cronet的User-AgentDummy/1.0

观察到 User-AgentDummy/1.0,说明 Cronet 拦截请求成功

Wireshare

为了避开 Apple 自身 QUIC 的干扰,我们故意把 Apple QUIC 关闭

ini 复制代码
request.assumesHTTP3Capable = NO;

通过 Wireshark 的过滤规则,我们过滤出 本机Mac 和 h2o.examp1e.net 的ip

ini 复制代码
(ip.src==132.226.1.140 and ip.dst==10.6.0.107 ) or (ip.src==10.6.0.107 and ip.dst== 132.226.1.140)

可以看到 Protocol 是 QUIC, 在demo中也将识别出的 Protocol显示出来是 H3

稍等片刻,再次发起同样的请求,我们也能很轻易观察到 0-RTT现象,这对网络传输提速是非常有用的

通过以上测试可以得到结论,集成的Cronet工作正常,对支持H3的请求使用的是QUIC协议。

五、其他讨论

Apple 的 NSURLSession 自身有很多好处,不用开发者参与即可自动支持,Cronet 是否也是呢?如下

NSURLSession Cronet
QUIC
IPv6
TCP Fast Open
TLS 1.3
Multipath TCP

Cronet 使用还在探索之中,如有错误之处,欢迎指出一起讨论。

相关推荐
tiantian_cool7 小时前
Claude Code 四大核心技能使用指南
ios
冰淇淋真好吃10 小时前
iOS实现 WKWebView 长截图的优雅方案
ios
前端不太难15 小时前
Flutter / RN / iOS,在长期维护下的性能差异本质
flutter·ios
搜狐技术产品小编20232 天前
精通 UITableViewDiffableDataSource——从入门到重构的现代 iOS 列表开发指南
ios·重构
tangweiguo030519872 天前
SwiftUI 状态管理完全指南:从 @State 到 @EnvironmentObject
ios
Digitally2 天前
如何轻松地将文件从 PC 传输到 iPhone
ios·iphone
iosTiov2 天前
当IPA遇见信任:解密ios生态中“签名”的真正力量
ios·团队开发·苹果签名·稳定
游戏开发爱好者82 天前
如何使用 AppUploader 提交上传 iOS 应用
android·ios·小程序·https·uni-app·iphone·webview
和沐阳学逆向2 天前
iOS 18 越狱教程:palera1n + 巨魔安装全流程
ios·巨魔商店·ios越狱·ios18越狱
ii_best3 天前
安卓/ios脚本开发辅助工具按键精灵横纵坐标转换教程
android·开发语言·ios·安卓