Sobes.tech
Middle

Ce soluție ai folosit pentru a lucra cu WebSocket?

sobes.tech AI

Răspuns de la AI

În proiecte unde era necesară o comunicare bidirecțională în timp real, am folosit cu succes URLSessionWebSocketTask.

Aceasta este o soluție încorporată în framework-ul Network, disponibilă începând cu iOS 13.

Avantajele URLSessionWebSocketTask:

  • Nativ: Integrat cu URLSession, ceea ce simplifică gestionarea conexiunilor și procesarea evenimentelor de rețea.
  • Performanță: Optimizat pentru funcționarea în rețea la nivel de sistem.
  • Fiabilitate: Mecanism încorporat de ping și pong, încercări automate de reconectare (deși poate fi necesară logică suplimentară pentru scenarii complexe).
  • Securitate: Suportă TLS din fabrică.

Pașii principali:

  1. Crearea unei instanțe URLSessionWebSocketTask.

    // Crearea unei instanțe URLSession cu setări implicite
    let session = URLSession(configuration: .default)
    // Inițializarea sarcinii WebSocket
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Începerea conexiunii.

    // Reînceperea sarcinii pentru stabilirea conexiunii
    webSocketTask.resume()
    
  3. Trimiterea mesajelor (text sau date binare).

    // Trimiterea unui mesaj text
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Eroare la trimitere: \(error)")
        }
    }
    
    // Trimiterea datelor binare
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Eroare la trimitere: \(error)")
        }
    }
    
  4. Primirea mesajelor. Acesta este un proces asincron.

    // Funcție recursivă pentru primirea mesajelor
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Eroare la primire: \(error)")
                // Tratarea erorii, posibil încercarea de reconectare
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Mesaj text primit: \(text)")
                case .data(let data):
                    print("Date binare primite: \(data)")
                @unknown default:
                    fatalError("Tip de mesaj necunoscut")
                }
                // Continuăm să ascultăm mesaje
                self.receiveMessage()
            }
        }
    }
    
    // Începerea ascultătorului
    receiveMessage()
    
  5. Tratarea evenimentelor ciclului de viață al conexiunii (deschidere, închidere, erori) folosind delegate-ul URLSessionWebSocketDelegate.

    // Exemplu de implementare a delegate-ului
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Conexiune deschisă")
            // Începerea primirii mesajelor după deschidere
            receiveMessage() // Se presupune că receiveMessage este definit
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Motiv necunoscut"
            print("Conexiune închisă cu codul \(closeCode.rawValue), motiv: \(reasonString)")
            // Logica de reconectare sau de încheiere
        }
    
        // Tratarea erorilor sesiunii
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Sarcina s-a încheiat cu eroare: \(error)")
                // Logica suplimentară de tratare a erorilor
            }
        }
    }
    
    // La crearea sesiunii, se folosește delegate-ul
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

De asemenea, am folosit biblioteci terțe, cum ar fi Starscream, atunci când era nevoie de suport pentru versiuni mai vechi de iOS sau anumite funcționalități absente în soluția nativă (de exemplu, reconectare automată cu backoff exponențial). Cu toate acestea, dacă este posibil, am preferat URLSessionWebSocketTask din cauza avantajelor menționate anterior.