1. WebSocket 基础
1.1 什么是 WebSocket?
- 全双工通信协议:基于 TCP,允许客户端与服务器建立持久连接,双方可主动发送数据。
- 实时性:替代 HTTP 轮询,适用于实时聊天、股票行情、在线游戏等场景。
- 协议升级 :通过 HTTP 握手(
Upgrade: websocket
)建立连接,后续通过 WebSocket 帧通信。
1.2 与 HTTP 对比
特性 | HTTP | WebSocket |
---|---|---|
连接方式 | 短连接(请求-响应后断开) | 长连接(持久化,双向通信) |
通信方向 | 单向(客户端主动请求) | 双向(客户端/服务器均可主动发送) |
头部开销 | 每次请求携带完整 HTTP 头 | 初始握手后,数据帧头部极小 |
适用场景 | 静态资源获取、REST API | 实时数据传输(如聊天、推送) |
2. iOS 中 WebSocket 的实现方式
2.1 官方方案:URLSessionWebSocketTask
(iOS 13+)
- 核心类 :
URLSessionWebSocketTask
(属于URLSession
框架) - 特点 :
- 原生支持,无需第三方库。
- 支持 iOS 13+,兼容性有限。
- 提供基本连接管理、消息发送/接收功能。
基本使用流程:
swift
// 1. 创建 URLSession 实例
let session = URLSession(configuration: .default)
// 2. 创建 WebSocketTask
guard let url = URL(string: "wss://your-server.com/socket") else { return }
let webSocketTask = session.webSocketTask(with: url)
// 3. 建立连接
webSocketTask.resume()
// 4. 接收消息
func receiveMessage() {
webSocketTask.receive { [weak self] result in
switch result {
case .success(let message):
switch message {
case .data(let data):
print("收到二进制数据: \(data)")
case .string(let text):
print("收到文本消息: \(text)")
}
// 继续监听下一条消息
self?.receiveMessage()
case .failure(let error):
print("接收失败: \(error)")
}
}
}
// 5. 发送消息(文本)
webSocketTask.send(.string("Hello Server")) { error in
if let error = error {
print("发送失败: \(error)")
}
}
// 6. 关闭连接
webSocketTask.cancel(with: .goingAway, reason: nil)
2.2 第三方库:Starscream
- 适用场景:支持 iOS 11+,功能更丰富(如 SSL 验证、自定义头、自动重连)。
- 集成方式:通过 CocoaPods 或 SPM 安装。
基本使用:
swift
import Starscream
// 1. 创建 WebSocket 实例
var request = URLRequest(url: URL(string: "wss://your-server.com/socket")!)
request.setValue("Bearer token", forHTTPHeaderField: "Authorization")
let socket = WebSocket(request: request)
// 2. 设置代理
socket.delegate = self
// 3. 连接服务器
socket.connect()
// 4. 发送消息
socket.write(string: "Hello Server")
// 5. 关闭连接
socket.disconnect()
// 实现 WebSocketDelegate
extension ViewController: WebSocketDelegate {
func didReceive(event: WebSocketEvent, client: WebSocket) {
switch event {
case .connected(let headers):
print("连接成功: \(headers)")
case .disconnected(let reason, let code):
print("断开连接: \(reason), code: \(code)")
case .text(let text):
print("收到文本: \(text)")
case .binary(let data):
print("收到二进制数据: \(data)")
case .error(let error):
print("错误: \(error?.localizedDescription ?? "")")
case .cancelled:
print("连接取消")
default:
break
}
}
}
3. 核心功能与最佳实践
3.1 连接管理
-
心跳机制(Ping/Pong) :定期发送 Ping 帧检测连接活性。
swift// URLSessionWebSocketTask webSocketTask.sendPing { error in if let error = error { print("Ping 失败: \(error)") } } // Starscream socket.write(ping: Data()) // 发送 Ping
-
自动重连:网络中断后自动尝试重新连接(需第三方库支持或自定义逻辑)。
3.2 消息处理
-
数据类型:支持文本(String)、二进制(Data)。
-
序列化 :常用 JSON 格式传输结构化数据。
swift// 发送 JSON let message = ["type": "chat", "content": "Hello"] if let data = try? JSONEncoder().encode(message) { webSocketTask.send(.data(data)) { /* 处理错误 */ } }
3.3 线程安全
-
主线程更新 UI :在接收消息的回调中切换至主线程更新界面。
swiftDispatchQueue.main.async { self.label.text = receivedText }
3.4 错误处理与断线重连
- 监听错误事件:捕获连接错误、消息发送失败等。
- 重连策略:指数退避重试(如 1s、2s、4s...)。
4. 安全性
- 使用
wss://
:WebSocket Secure(基于 TLS 加密)。 - 证书验证 :在
URLSessionDelegate
中处理 SSL 证书校验(如需自定义)。 - 身份验证 :通过 HTTP 头(如
Authorization: Bearer token
)或握手阶段传递 Token。
5. 性能优化
- 消息压缩:服务器启用 WebSocket 扩展(如 permessage-deflate)。
- 连接复用:避免频繁创建/销毁连接。
- 数据量控制:避免单次发送过大消息(分片传输)。
6. 常见问题与解决方案
问题 | 解决方案 |
---|---|
连接不稳定 | 实现自动重连逻辑,监听网络状态变化(如 Network.framework )。 |
内存泄漏 | 使用 [weak self] 避免循环引用,及时释放不再使用的 WebSocket 实例。 |
后台连接断开 | 启用后台模式(需配置 Capabilities > Background Modes > Remote notifications )。 |
消息顺序混乱 | 在消息中添加序列号,客户端按序处理。 |
7. 适用场景示例
- 实时聊天应用:消息即时推送、已读回执。
- 金融行情推送:实时股票价格、K线数据。
- 多人在线游戏:玩家位置同步、状态更新。
- 物联网控制:设备状态监控、指令下发。
总结
- 核心价值:WebSocket 为 iOS 应用提供高效、实时的双向通信能力。
- 选择方案 :优先使用
URLSessionWebSocketTask
(iOS 13+),低版本或需高级功能时选择 Starscream。 - 关键实践:心跳保活、错误重连、数据序列化、线程安全。