引言:为什么SSE是你最好的新朋友
想象一下:你坐在舒适的咖啡馆里,喝着咖啡,而你的iOS应用在后台接收最新的汇率、新消息通知或来自物联网设备传感器的数据。这一切——无需不断向服务器发送ping请求、无需消耗电池、也无需像WebSocket那样复杂的协议。认识一下:Swift中的服务器发送事件(SSE)——这项技术让数据流变得如此简单,你会惊讶为什么之前没有使用它。
在本文中,我们将探讨如何为iOS、macOS、watchOS和tvOS实现Swift中的服务器发送事件。你将了解为什么SSE通常比WebSocket更方便、如何从头编写自己的SSE客户端,以及新手会遇到哪些陷阱。我们开始吧!
什么是服务器发送事件以及为什么需要它们?
服务器发送事件是W3C标准,允许服务器通过单个HTTP连接向客户端发送数据。与WebSocket不同,SSE仅单向工作(服务器→客户端),但这恰恰使其成为不需要双向通信的任务的理想选择。
何时选择SSE而不是WebSocket?
- 通知和警报——服务器发送事件,客户端只读取。
- 流式数据——股票报价、服务器指标、GPS跟踪。
- 新闻推送——类似Twitter的更新。
- 执行进度——文件上传、视频处理。
SSE相对于WebSocket的主要优势在于简单。你不需要单独的协议,普通的HTTP就足够了。这意味着任何基于Python、Node.js或Go的服务器都可以无需额外库向你的Swift应用发送事件。
SSE如何工作:解析协议
服务器发送一个普通的HTTP响应,带有头信息Content-Type: text/event-stream。数据格式如下:
event: messagedata: {"text": "你好,世界!"}id: 42
event: updatedata: {"count": 10}retry: 3000关键字段:
event——事件类型(可选)。data——事件主体(可以是多行)。id——用于恢复连接的标识符。retry——出错时重新连接前的等待时间(毫秒)。
每个事件由两个换行符分隔。很简单,对吧?
在Swift中创建SSE客户端:从简单到复杂
Foundation标准库中没有现成的SSE类,但自己编写一个只需15分钟。我们使用带有代理的URLSession来处理流式数据。
步骤1:基础EventSource类
import Foundation
final class EventSource: NSObject { private var url: URL private var session: URLSession? private var task: URLSessionDataTask? private var currentData = Data() private var lastEventId: String? var onEvent: ((String, String) -> Void)? // event, data var onError: ((Error) -> Void)? var onOpen: (() -> Void)? init(url: URL) { self.url = url super.init() } func connect() { var request = URLRequest(url: url) request.setValue("text/event-stream", forHTTPHeaderField: "Accept") if let lastId = lastEventId { request.setValue(lastId, forHTTPHeaderField: "Last-Event-ID") } let config = URLSessionConfiguration.default config.timeoutIntervalForRequest = TimeInterval(INT_MAX) config.timeoutIntervalForResource = TimeInterval(INT_MAX) session = URLSession(configuration: config, delegate: self, delegateQueue: nil) task = session?.dataTask(with: request) task?.resume() } \