HTTP/HTTPS/HTTP2 协议
问题
Android 网络开发中常涉及的 HTTP 协议核心知识有哪些?
答案
HTTP/1.1 核心要点
持久连接(Keep-Alive)
HTTP/1.1 默认启用持久连接,一个 TCP 连接可以发送多个请求:
Connection: keep-alive
但 HTTP/1.1 存在队头阻塞(Head-of-Line Blocking)—— 同一连接上的请求必须按顺序处理,前一个请求未完成会阻塞后续请求。浏览器通常为每个域名开 6 个 TCP 连接来缓解此问题。
常见请求方法
| 方法 | 语义 | 幂等 | 安全 |
|---|---|---|---|
| GET | 获取资源 | ✅ | ✅ |
| POST | 创建资源 | ❌ | ❌ |
| PUT | 替换资源 | ✅ | ❌ |
| PATCH | 部分更新 | ❌ | ❌ |
| DELETE | 删除资源 | ✅ | ❌ |
常见状态码
| 状态码 | 含义 | Android 处理策略 |
|---|---|---|
| 200 | 成功 | 正常解析 |
| 301/302 | 重定向 | OkHttp 自动跟随 |
| 304 | 未修改 | 使用本地缓存 |
| 401 | 未认证 | 触发 Authenticator |
| 403 | 禁止访问 | 提示权限不足 |
| 404 | 未找到 | 提示资源不存在 |
| 429 | 请求过多 | 实现退避重试 |
| 500 | 服务器错误 | 提示服务异常 |
HTTPS 与 TLS
TLS 握手流程
Android 证书固定(Certificate Pinning)
防止中间人攻击,将服务端证书的公钥哈希固定在客户端:
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAA=") // 主证书
.add("api.example.com", "sha256/BBBBBBB=") // 备用证书
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
证书固定的风险
证书过期或更换后,如果客户端未及时更新,将无法连接服务器。建议同时固定备用证书,并预留远程更新机制。
Network Security Configuration
Android 7.0+ 支持通过 XML 配置网络安全策略:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 仅调试模式允许自签名证书 -->
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
<!-- 指定域名的证书固定 -->
<domain-config>
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2025-01-01">
<pin digest="SHA-256">AAAAAAA=</pin>
</pin-set>
</domain-config>
</network-security-config>
HTTP/2 与 HTTP/3
HTTP/2 核心特性
| 特性 | 说明 |
|---|---|
| 多路复用 | 一个 TCP 连接并行传输多个请求/响应,解决 HTTP/1.1 队头阻塞 |
| 二进制帧 | 数据以二进制帧传输,比文本协议更高效 |
| 头部压缩 | HPACK 压缩算法减少重复 Header 传输 |
| 服务器推送 | 服务端主动推送资源(实际使用较少) |
// OkHttp 默认支持 HTTP/2(TLS 环境自动协商)
val client = OkHttpClient.Builder()
.protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
.build()
HTTP/3 (QUIC)
HTTP/3 基于 UDP 上的 QUIC 协议:
- 0-RTT 连接建立:跳过 TCP 握手
- 无队头阻塞:流级别独立,一个流的丢包不影响其他流
- 连接迁移:网络切换(Wi-Fi → 4G)不需要重新握手
Android 对 HTTP/3 的支持
Android 通过 Cronet(Chrome 网络库)支持 QUIC/HTTP3。OkHttp 本身暂不支持 HTTP/3。Google 的 com.google.android.gms:play-services-cronet 提供了 Cronet 集成。
常见面试问题
Q1: HTTP 和 HTTPS 的区别?
答案:
HTTPS = HTTP + TLS。区别:
| 特性 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 加密 | ❌ 明文 | ✅ TLS 加密 |
| 证书 | 不需要 | 需要 CA 签发证书 |
| 性能 | 无握手开销 | TLS 握手增加 1-2 RTT |
| 安全 | 易被窃听、篡改 | 防窃听、防篡改、防伪造 |
Android 9+ 默认禁止明文 HTTP 请求(android:usesCleartextTraffic="false")。
Q2: HTTP/2 相比 HTTP/1.1 有什么优势?
答案:
- 多路复用:一个连接上可并行发送多个请求,不再需要多个 TCP 连接
- 二进制分帧:效率更高,解析更快
- HPACK 头部压缩:减少重复 Header 传输(如 Cookie、User-Agent)
- 流优先级:可以设置请求优先级
OkHttp 通过 ALPN(Application-Layer Protocol Negotiation)在 TLS 握手时自动协商 HTTP/2。
Q3: 对称加密和非对称加密在 HTTPS 中如何配合?
答案:
TLS 使用混合加密:
- 非对称加密(RSA/ECDHE):在握手阶段交换预主密钥,安全但计算慢
- 对称加密(AES-GCM):双方从预主密钥推导出会话密钥,之后所有数据传输都用对称加密,快速高效
简单说:非对称加密解决密钥分发问题,对称加密解决数据传输效率问题。