Swift 上的 WebSocket:为 iOS 和 macOS 创建实时应用

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

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

开始课程

Swift中WebSocket简介:从理论到实践



现代移动和桌面应用越来越需要即时数据传输。无论是聊天软件、股票交易终端、在线游戏还是监控系统——用户都期望信息能实时更新,无需不断刷新屏幕。这时WebSocket协议就派上了用场。



与经典的HTTP请求(基于"请求-响应"原理)不同,WebSocket在客户端和服务器之间建立永久双向连接。这意味着服务器可以在无需事先请求的情况下随时向客户端发送数据。在Apple生态系统中,既有原生解决方案(URLSessionWebSocketTask),也有流行的第三方库(如Starscream)可用于WebSocket开发。



本文将介绍如何将WebSocket集成到适用于iOS和macOS的Swift应用中,编写可运行的代码示例,并分享最佳实践。



1. 通过URLSession实现原生WebSocket



从iOS 13和macOS 10.15开始,Apple通过URLSessionWebSocketTask类提供了内置的WebSocket支持。这是最简单且推荐的方法,无需安装第三方依赖。



创建和配置连接



首先,需要创建一个URLSession实例并设置其配置。然后使用ws://协议(安全连接使用wss://)构造URL,并创建WebSocket任务。



import Foundation

class WebSocketManager: NSObject { private var webSocketTask: URLSessionWebSocketTask? private let session: URLSession override init() { let config = URLSessionConfiguration.default self.session = URLSession(configuration: config, delegate: nil, delegateQueue: OperationQueue()) super.init() } func connect() { guard let url = URL(string: "wss://echo.websocket.org") else { return } webSocketTask = session.webSocketTask(with: url) webSocketTask?.resume() receiveMessage() } func disconnect() { webSocketTask?.cancel(with: .normalClosure, reason: nil) }}


发送和接收消息



WebSocket支持发送文本(URLSessionWebSocketTask.Message.string)和二进制数据(.data)。要接收消息,需要递归调用receive方法,因为它每次只处理一条消息。



extension WebSocketManager {    func sendMessage(_ text: String) {        let message = URLSessionWebSocketTask.Message.string(text)        webSocketTask?.send(message) { error in            if let error = error {                print("Send error: \\(error.localizedDescription)")            }        }    }        private func receiveMessage() {        webSocketTask?.receive { [weak self] result in            switch result {            case .success(let message):                switch message {                case .string(let text):                    print("Received text message: \\(text)")                case .data(let data):                    print("Received binary data: \\(data.count) bytes")                @unknown default:                    print("Unknown message type")                }                // 递归继续监听                self?.receiveMessage()            case .failure(let error):                print("Receive error: \\(error.localizedDescription)")            }        }    }}


注意成功闭包内对receiveMessage()的递归调用——这能确保应用持续接收新数据。

博客

书籍推荐