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

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

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

Начать курс

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                    

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