Swift (iOS/macOS) WebSocket 库:Starscream 和 URLSessionWebSocketTask
WebSocket 是一种协议,可在客户端(iOS/macOS 应用)和服务器之间建立持久的双向连接。与 HTTP 不同,建立连接后,数据可以实时传输,无需重复请求。对于 Swift,有两种主要方法:使用内置的 URLSessionWebSocketTask(自 iOS 13/macOS 10.15 起可用)和第三方库 Starscream(支持更旧的版本并提供扩展功能)。
1. URLSessionWebSocketTask — Swift 原生 WebSocket
从 iOS 13 和 macOS 10.15 开始,Apple 直接在 URLSession 中添加了对 WebSocket 的支持。这意味着对于基本场景,无需安装额外的依赖项。
连接和发送消息示例
import Foundation
class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private let session = URLSession(configuration: .default) func connect() { guard let url = URL(string: "wss://echo.websocket.org") else { return } webSocketTask = session.webSocketTask(with: url) webSocketTask?.resume() receiveMessage() } func sendMessage(_ text: String) { let message = URLSessionWebSocketTask.Message.string(text) webSocketTask?.send(message) { error in if let error = error { print("发送错误:\\(error.localizedDescription)") } } } private func receiveMessage() { webSocketTask?.receive { [weak self] result in switch result { case .success(let message): switch message { case .string(let text): print("收到:\\(text)") case .data(let data): print("收到二进制数据:\\(data.count) 字节") @unknown default: break } self?.receiveMessage() // 继续监听 case .failure(let error): print("接收错误:\\(error.localizedDescription)") } } } func disconnect() { webSocketTask?.cancel(with: .normalClosure, reason: nil) }}URLSessionWebSocketTask 的优点
- 无依赖 — 系统已内置所有功能。
- 原生集成 后台任务和 App Transport Security。
- 支持 Apple 随操作系统更新。
缺点
- 最低版本要求 iOS 13 / macOS 10.15。
- 缺少内置的重连和 ping/pong 支持(需要手动实现)。
- 配置灵活性较低。
2. Starscream — 强大灵活的 Swift WebSocket 库
Starscream 是最流行的第三方 Swift WebSocket 库。它支持 iOS 8+、macOS 10.10+,以及 watchOS 和 tvOS。Starscream 提供内置的重连机制、自动 ping/pong 和 SSL/TLS 支持。
通过 Swift Package Manager 安装
// 在 Package.swift 或通过 Xcode:File → Add Packages...// URL:https://github.com/daltoniam/Starscream.git// 版本:4.0.0 及以上Starscream 使用示例
import Starscream
class StarscreamManager: WebSocketDelegate { var socket: WebSocket? func setupConnection() { var request = URLRequest(url: URL(string: "wss://echo.websocket.org")!) request.timeoutInterval = 5 socket = WebSocket(request: request) socket?.delegate = self socket?.connect() }\