Sobes.tech
Middle

Kokią sprendimą naudojote dirbant su WebSocket?

sobes.tech AI

Atsakymas iš AI

Projektuose, kur reikėjo dvipusio ryšio realiuoju laiku, sėkmingai naudoju URLSessionWebSocketTask:

Tai įmontuotas sprendimas Network karkaso, prieinamas nuo iOS 13:

URLSessionWebSocketTask privalumai:

  • Gili natyvumas: Integruotas su URLSession, palengvinantis ryšio valdymą ir tinklo įvykių apdorojimą.
  • Veikimas: Optimizuotas tinklo operacijoms sistemos lygiu.
  • Patikimumas: Vidinis ping ir pong mechanizmas, automatinis prisijungimo atnaujinimas (nors gali prireikti papildomos logikos sudėtingiems scenarijams).
  • Saugumas: Parama TLS iš karto.

Pagrindiniai darbo žingsniai:

  1. Sukurti URLSessionWebSocketTask pavyzdį:

    // Sukurti `URLSession` su numatytais nustatymais
    let session = URLSession(configuration: .default)
    // WebSocket užduoties inicijavimas
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Pradėti ryšį:

    // Atkurti užduotį ryšio nustatymui
    webSocketTask.resume()
    
  3. Siųsti žinutes (tekstines arba binarines duomenis):

    // Siųsti tekstinę žinutę
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Klaida siuntimo metu: \(error)")
        }
    }
    
    // Siųsti binarinius duomenis
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Klaida siuntimo metu: \(error)")
        }
    }
    
  4. Gauti žinutes. Tai asinchroninis procesas:

    // Rekursinė funkcija žinučių priėmimui
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Klaida priimant: \(error)")
                // Klaidos apdorojimas, galbūt bandymas vėl prisijungti
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Gauta tekstinė žinutė: \(text)")
                case .data(let data):
                    print("Gauti binariniai duomenys: \(data)")
                @unknown default:
                    fatalError("Nežinomas žinutės tipas")
                }
                // Tęsti žinučių klausymą
                self.receiveMessage()
            }
        }
    }
    
    // Pradėti klausymą
    receiveMessage()
    
  5. Valdyti ryšio ciklo įvykius (atidarymas, uždarymas, klaidos) naudojant URLSessionWebSocketDelegate:

    // Delegato pavyzdys
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Ryšys atidarytas")
            // Pradėti žinučių priėmimą po atidarymo
            receiveMessage() // Tikėtina, kad `receiveMessage` yra apibrėžta
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Nežinoma priežastis"
            print("Ryšys uždarytas su kodu \(closeCode.rawValue), priežastis: \(reasonString)")
            // Perjungimo arba darbo pabaigos logika
        }
    
        // Sesijos klaidų apdorojimas
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Užduotis baigėsi su klaida: \(error)")
                // Papildoma klaidų apdorojimo logika
            }
        }
    }
    
    // Sukurti sesiją su delegatu
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

Taip pat naudoju trečiųjų šalių bibliotekas, tokias kaip Starscream, kai reikėjo palaikyti senesnes iOS versijas arba tam tikras funkcijas, kurios nėra natūralioje sprendime (pavyzdžiui, automatinis prisijungimo pakartojimas su eksponentiniu vėlavimu). Tačiau, jei įmanoma, pirmenybę teikiau URLSessionWebSocketTask dėl aukščiau išvardytų pranašumų.