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:
-
Sukurti
URLSessionWebSocketTaskpavyzdį:// 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")!) -
Pradėti ryšį:
// Atkurti užduotį ryšio nustatymui webSocketTask.resume() -
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)") } } -
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() -
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ų.