1. 网络基础回顾:HTTP/HTTPS协议、TCP与UDP、RESTful API设计原则、iOS网络沙盒与ATS

好,咱们正式开始。第一节课,我不会一上来就扔一堆高大上的架构图。先打好地基,把网络世界里那些最基础、也最容易踩坑的东西捋一遍。你可能会觉得「这些我都知道」,但说实话,很多线上事故,恰恰就出在这些「知道」的细节上。

1.1 HTTP/HTTPS:不只是多了个S

HTTP,超文本传输协议。说白了,就是客户端和服务器之间约定好的一种「说话方式」。你发请求,我回响应,就这么简单。但问题在于,HTTP是明文传输的。你想想看,你在咖啡厅连个公共Wi-Fi,发的所有数据包,别人用个抓包工具就能看得一清二楚。这多可怕。

所以就有了HTTPS。它其实是在HTTP和TCP之间加了一层SSL/TLS加密层。我个人习惯把HTTPS理解为「HTTP + 加密 + 身份验证」。它解决了三个核心问题:

  • 机密性:数据加密,中间人看不懂
  • 完整性:数据不被篡改
  • 身份验证:你连接的是真正的服务器,不是冒牌货

我在项目中遇到过一件事:有个同事调试接口,发现偶尔返回的数据是乱码。查了半天,原来是服务器端的HTTPS证书配置有问题,导致部分请求被中间设备劫持并解密失败。嗯,从那以后,我每次对接第三方API,第一件事就是检查证书链是否完整。

核心要点:iOS 9之后,ATS(App Transport Security)默认强制使用HTTPS。如果你还在用HTTP,Info.plist里必须加例外。但我的建议是——别偷懒,能用HTTPS就别用HTTP。

1.2 TCP与UDP:一个要稳,一个要快

这两个协议,是传输层的两大支柱。我经常跟团队里的新人说:TCP是快递员,必须送到你手上,签收才算完;UDP是广播喇叭,喊一嗓子,谁听见算谁的。

特性 TCP UDP
连接方式 面向连接(三次握手) 无连接
可靠性 可靠传输,有重传机制 不可靠,丢包不重传
顺序性 保证数据包顺序 不保证顺序
速度 相对较慢 快,低延迟
典型应用 HTTP、FTP、邮件 视频直播、在线游戏、DNS

为什么会这样?TCP为了保证数据不丢、不乱序,做了很多额外工作:三次握手建立连接、滑动窗口做流量控制、拥塞控制避免网络崩溃。这些机制保证了可靠性,但也带来了延迟。

我曾经在做一个实时对战游戏时,一开始用了TCP。结果发现,一旦网络波动,玩家操作延迟高得离谱。后来换成UDP + 自定义重传逻辑,体验瞬间好了很多。说白了,选哪个协议,取决于你的业务场景:

  • 要数据完整、不能出错?用TCP。
  • 要低延迟、能容忍少量丢包?用UDP。

避坑指南:我曾经在iOS上用UDP做音视频传输,结果发现Wi-Fi和4G切换时,UDP连接会断。后来加了心跳包和重连机制才解决。记住,UDP虽然无连接,但应用层你得自己管连接状态。

1.3 RESTful API设计原则:让接口像人话

RESTful,说白了就是一套设计API的规范。它的核心思想是:把服务器上的资源抽象成URL,用HTTP动词(GET、POST、PUT、DELETE)来操作这些资源。

我见过太多乱七八糟的接口了。比如:/getUserInfo/deleteUserById/updateUserData。这其实是在用RPC的思路写REST。真正的RESTful应该是这样的:

GET    /users          // 获取用户列表
GET    /users/123      // 获取ID为123的用户
POST   /users          // 创建新用户
PUT    /users/123      // 更新ID为123的用户
DELETE /users/123      // 删除ID为123的用户

你看,URL只描述资源,动词描述操作。这样设计的好处是:接口语义清晰,前端一看就懂。我个人习惯在团队里定一条铁律:URL里不准出现动词,只能用名词复数形式。

还有几个关键原则:

  • 无状态:每个请求都包含所有必要信息,服务器不保存客户端状态
  • 统一接口:所有资源都用同样的方式操作
  • 使用HTTP状态码:200表示成功,404表示找不到,500表示服务器挂了

注意:RESTful不是银弹。如果你的业务场景需要复杂的批量操作或事务,RESTful可能会很别扭。这时候可以考虑GraphQL或者RPC。但话说回来,80%的移动端API,RESTful完全够用。

1.4 iOS网络沙盒与ATS:苹果的「安全强迫症」

iOS的沙盒机制,说白了就是每个App都活在自己的小隔间里。你不能随便访问其他App的数据,也不能随意读写系统文件。网络请求也不例外——你的App只能访问你主动发起的网络连接,不能监听别人的网络流量。

但真正让开发者头疼的,是ATS(App Transport Security)。这是iOS 9引入的一项安全策略,默认要求所有网络连接都使用HTTPS。如果你非要连HTTP,必须在Info.plist里声明例外。

我记得有一次,App上线前测试,发现某个第三方SDK还在用HTTP。结果在iOS 10以上的设备上,请求直接失败,连错误日志都不好找。后来排查了半天,才发现是ATS拦截了。

配置ATS的典型做法:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

但我的建议是:永远不要设置 NSAllowsArbitraryLoads = YES。这等于把安全大门全敞开了。苹果审核看到这个,大概率会拒绝你的App。正确的做法是:逐个域名添加例外,并且只对确实需要HTTP的域名开放。

一句话总结:ATS不是来折磨你的,它是来保护你的用户的。尊重它,用好它。

好了,这一章的内容就到这里。网络基础部分看似简单,但每一个点都可能在实战中给你挖坑。下一章,我们会深入URLSession的底层原理,看看苹果到底是怎么帮我们发网络请求的。