WebSocket библиотеки для Swift (iOS/macOS): Starscream и URLSessionWebSocketTask
WebSocket — это протокол, обеспечивающий полнодуплексную связь между клиентом и сервером через одно TCP-соединение. В экосистеме Swift (iOS/macOS) существует два основных подхода для работы с WebSocket: нативная реализация URLSessionWebSocketTask (доступна с iOS 13/macOS 10.15) и популярная сторонняя библиотека Starscream. Обе позволяют создавать реактивные приложения с реальным временем: чаты, ленты котировок, многопользовательские игры и т.д.
Нативная реализация URLSessionWebSocketTask
С выходом iOS 13 компания Apple добавила встроенную поддержку WebSocket в фреймворк Foundation. Это избавляет от необходимости подключать сторонние зависимости, если ваше приложение ориентировано на современные версии ОС.
Основные возможности:
- Полностью асинхронная работа через
async/awaitили callback'и - Автоматическое управление жизненным циклом соединения
- Поддержка
closeCode,closeReasonдля корректного завершения - Встроенная работа с
URLSession(поддержка таймаутов, политик кэширования)
Пример подключения и отправки сообщения:
import Foundation
class WebSocketManager {
private var webSocketTask: URLSessionWebSocketTask?
private let session = URLSession.shared
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)")
@unknown default:
fatalError()
}
// Продолжаем слушать
self?.receiveMessage()
case .failure(let error):
print("Ошибка получения: \(error)")
// Возможно, переподключение
}
}
}
func disconnect() {
webSocketTask?.cancel(with: .normalClosure, reason: nil)
}
}
Starscream — гибкая и проверенная библиотека
Starscream — это open-source WebSocket библиотека для Swift, написанная Dalton Cherry и поддерживаемая сообществом. Она работает на iOS, macOS, tvOS и watchOS, начиная с более старых версий (iOS 8+). Starscream предоставляет больше контроля над соединением и поддерживает дополнительные функции, такие как сжатие (permessage-deflate) и кастомные заголовки.
Установка через Swift Package Manager:
// В Package.swift или через Xcode: File → Swift Packages → Add Package Dependency
.package(url: "https://github.com/daltoniam/Starscream.git", from: "4.0.0")
Основные возможности:
- Поддержка
WebSocketDelegateдля всех событий (подключение, получение данных, ошибки, отключение) - Ручное управление пингами/понгами для поддержания соединения
- Возможность отправки бинарных данных (Data) и строк (String/UTF-8)
- Поддержка SSL/TLS и самоподписанных сертификатов
- Встроенная поддержка
Combineчерез publisher'ы (начиная с версии 4.0)
Пример использования Starscream с делегатом:
import Starscream
class SocketService: WebSocketDelegate {
var socket: WebSocket!
init() {
var request = URLRequest(url: URL(string: "wss://echo.websocket.org")!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
// MARK: - WebSocketDelegate
func didReceive(event: WebSocketEvent, client: WebSocket) {
switch event {
case .connected(let headers):
print("Подключено: \(headers)")
// Отправляем приветственное сообщение
client.write(string: "Hello Server!")
case .disconnected(let reason, let code):
print("Отключено: \(reason) (код: \(code))")
case .text(let string):
print("Получен текст: \(string)")
case .binary(let data):
print("Получены данные: \(data)")
case .ping(_):
break
case .pong(_):
break
case .viabilityChanged(_):
break
case .reconnectSuggested(_):
break
case .canc