Sobes.tech
Middle

Aké riešenie ste použili na prácu s WebSocket?

sobes.tech AI

Odpoveď od AI

V projektoch, kde bola požadovaná obojsmerná komunikácia v reálnom čase, som úspešne použil URLSessionWebSocketTask.

Je to vstavané riešenie rámca Network, dostupné od iOS 13.

Výhody URLSessionWebSocketTask:

  • Nativita: Integrované s URLSession, čo zjednodušuje správu spojení a spracovanie sieťových udalostí.
  • Výkon: Optimalizované pre sieťovú komunikáciu na úrovni systému.
  • Spoľahlivosť: Vstavaný mechanizmus pingov a pongov, automatické pokusy o opätovné pripojenie (hoci môže byť potrebná dodatočná logika pre zložité scenáre).
  • Bezpečnosť: Podporuje TLS priamo z krabice.

Hlavné kroky práce:

  1. Vytvorenie inštancie URLSessionWebSocketTask.

    // Vytvorenie inštancie URLSession s predvolenými nastaveniami
    let session = URLSession(configuration: .default)
    // Inicializácia WebSocket úlohy
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Spustenie spojenia.

    // Obnovenie úlohy na nadviazanie spojenia
    webSocketTask.resume()
    
  3. Odosielanie správ (textové alebo binárne dáta).

    // Odoslanie textovej správy
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Chyba pri odosielaní: \(error)")
        }
    }
    
    // Odoslanie binárnych dát
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Chyba pri odosielaní: \(error)")
        }
    }
    
  4. Prijímanie správ. Je to asynchrónny proces.

    // Rekurzívna funkcia na prijímanie správ
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Chyba pri prijímaní: \(error)")
                // Spracovanie chyby, možno pokus o opätovné pripojenie
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Prijatá textová správa: \(text)")
                case .data(let data):
                    print("Prijaté binárne dáta: \(data)")
                @unknown default:
                    fatalError("Neznámy typ správy")
                }
                // Pokračujeme v počúvaní správ
                self.receiveMessage()
            }
        }
    }
    
    // Spustenie počúvania
    receiveMessage()
    
  5. Spracovanie udalostí životného cyklu spojenia (otvorenie, zatvorenie, chyby) s použitím delegáta URLSessionWebSocketDelegate.

    // Príklad implementácie delegáta
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Spojenie otvorené")
            // Spustenie prijímania správ po otvorení
            receiveMessage() // Predpokladá sa, že receiveMessage je definovaná
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Neznámy dôvod"
            print("Spojenie zatvorené s kódom \(closeCode.rawValue), dôvod: \(reasonString)")
            // Logika opätovného pripojenia alebo ukončenia práce
        }
    
        // Spracovanie chýb relácie
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Úloha ukončená s chybou: \(error)")
                // Dodatočná logika spracovania chýb
            }
        }
    }
    
    // Pri vytváraní relácie použiť delegáta
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

Použil som tiež tretie strany knižnice, ako je Starscream, keď bola požadovaná podpora starších verzií iOS alebo určité funkcie, ktoré chýbali v natívnom riešení (napríklad automatické opätovné pripojenie s exponenciálnou spätnou väzbou). Avšak, ak je to možné, uprednostňoval som URLSessionWebSocketTask kvôli vyššie uvedeným výhodám.