Sobes.tech
Middle

Koje rešenje ste koristili za rad sa WebSocket?

sobes.tech АИ

Одговор од АИ

У пројектима где је била потребна двосмерна комуникација у реалном времену, успешно сам користио URLSessionWebSocketTask.

Ово је уграђено решење из фрејмворка Network, доступно од iOS 13.

Предности URLSessionWebSocketTask:

  • Нативно: Интегрисано са URLSession, што олакшава управљање везама и обраду мрежних догађаја.
  • Перформансе: Оптимизовано за рад са мрежом на нивоу система.
  • Поузданост: Уграђени механизам пинг и пинг, аутоматски покушаји поновног повезивања (иако може бити потребна додатна логика за сложеније сценарије).
  • Безбедност: Подржава TLS из кутије.

Главни кораци:

  1. Креирање инстанце URLSessionWebSocketTask.

    // Креирање инстанце URLSession са подразумеваним подешавањима
    let session = URLSession(configuration: .default)
    // Инициализација WebSocket задатка
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Покретање везе.

    // Настављање задатка за успостављање везе
    webSocketTask.resume()
    
  3. Слање порука (текстуалних или бинарних података).

    // Слање текстуалне поруке
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Грешка при слању: \(error)")
        }
    }
    
    // Слање бинарних података
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Грешка при слању: \(error)")
        }
    }
    
  4. Примање порука. Ово је асинхрона процес.

    // Рекурсивна функција за примање порука
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Грешка при пријему: \(error)")
                // Обрада грешке, могуће покушај поновног повезивања
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Примљена текстуална порука: \(text)")
                case .data(let data):
                    print("Примљени бинарни подаци: \(data)")
                @unknown default:
                    fatalError("Непознат тип поруке")
                }
                // Настављамо слушање порука
                self.receiveMessage()
            }
        }
    }
    
    // Покретање слушача
    receiveMessage()
    
  5. Обрада догађаја животног циклуса везе (отварање, затварање, грешке) коришћењем делегата URLSessionWebSocketDelegate.

    // Пример имплементације делегата
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Веза отворена")
            // Почетак слушања порука након отварања
            receiveMessage() // претпоставља се да је receiveMessage дефинисан
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Непознат разлог"
            print("Веза затворена са кодом \(closeCode.rawValue), разлог: \(reasonString)")
            // Логика поновног повезивања или завршетка
        }
    
        // Обрада грешака сесије
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Завршетак задатка са грешком: \(error)")
                // Додатна логика обраде грешака
            }
        }
    }
    
    // При креирању сесије користити делегата
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

Такође сам користио библиотеке трећих страна као што је Starscream, када је била потребна подршка за старије верзије iOS или одређене функционалности које нису доступне у нативном решењу (нпр. аутоматско поновно повезивање са експоненцијалним закашњењем). Међутим, ако је могуће, преферирао сам URLSessionWebSocketTask због горе наведених предности.