Swift中的服务器发送事件:无需WebSocket的实时数据流

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么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() } \

博客

书籍推荐