WebSocket библиотеки Swift: Starscream и URLSessionWebSocketTask

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

WebSocket библиотеки для Swift (iOS/macOS): Starscream и URLSessionWebSocketTask

WebSocket — это протокол, обеспечивающий постоянное двустороннее соединение между клиентом (iOS/macOS приложением) и сервером. В отличие от HTTP, после установки соединения данные могут передаваться в реальном времени без повторных запросов. Для Swift существует два основных подхода: использование встроенного URLSessionWebSocketTask (доступен с iOS 13/macOS 10.15) и сторонняя библиотека Starscream (поддерживает более старые версии и предоставляет расширенный функционал).

1. URLSessionWebSocketTask — нативный WebSocket в Swift

Начиная с iOS 13 и macOS 10.15, Apple добавила поддержку WebSocket прямо в URLSession. Это означает, что для базовых сценариев не требуется устанавливать дополнительные зависимости.

Пример подключения и отправки сообщения

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.
  • Отсутствие встроенной поддержки reconnection и ping/pong (нужно реализовывать вручную).
  • Меньше гибкости в настройках.

2. Starscream — мощная и гибкая WebSocket библиотека для Swift

Starscream — самая популярная сторонняя WebSocket библиотека для Swift. Она поддерживает 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()
    }
    
    // MARK: - WebSocketDelegate
    func didReceive(event: WebSocketEvent, client: WebSocket) {
        switch event {
        case .connected(let headers):
            print("Подключено: \(headers)")
        case .disconnected(let reason, let code):
            print("Отключено: \(reason) (код \(code))")
        case .text(let string):
            print("Текст: \(string)")
        case .binary(let data):
            print("Бинарные данные: \(data)")
        case .ping(let data):
            print("Ping получен")
        case .pong(let data):
            print("Pong получен")
        case .viabilityChanged(let isViable):
            print("Соединение активно: \(isViable)")
        case .reconnectSuggested(let shouldReconnect):
            if shouldReconnect {
                print("Рекомендуется переподключение")
                client.connect()
            }
        case .cancelled:
            print("Соединение отменено")
        case .error(let error):
            print("Ошибка: \(error?.localizedDescription ?? "неизвестная")")
        }
    }
    
    func sendMessage(_ text: String) {
        socket?.write(string: text)
    }
    
    func disconnect() {
        socket?.disconnect()
    }
}

Преимущества Starscream

  • Обратная совместимость с iOS 8+.
  • Автоматический ping/pong для поддержа

Рекомендаций