Sobes.tech
Middle

Ποια λύση χρησιμοποιήσατε για να εργαστείτε με WebSocket;

sobes.tech AI

Απάντηση από AI

In projects where real-time bidirectional communication was required, I successfully used URLSessionWebSocketTask.

This is an built-in solution of the Network framework, available since iOS 13.

Advantages of URLSessionWebSocketTask:

  • Native: Integrated with URLSession, which simplifies connection management and network event handling.
  • Performance: Optimized for network operation at the system level.
  • Reliability: Built-in ping and pong mechanism, automatic reconnection attempts (though additional logic may be needed for complex scenarios).
  • Security: Supports TLS out of the box.

Main steps:

  1. Creating an instance of URLSessionWebSocketTask.

    // Creating a URLSession instance with default settings
    let session = URLSession(configuration: .default)
    // Initializing WebSocket task
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Starting the connection.

    // Resuming the task to establish the connection
    webSocketTask.resume()
    
  3. Sending messages (text or binary data).

    // Sending a text message
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Error sending: \(error)")
        }
    }
    
    // Sending binary data
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Error sending: \(error)")
        }
    }
    
  4. Receiving messages. This is an asynchronous process.

    // Recursive function to receive messages
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Error receiving: \(error)")
                // Error handling, possibly attempt reconnection
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Received text message: \(text)")
                case .data(let data):
                    print("Received binary data: \(data)")
                @unknown default:
                    fatalError("Unknown message type")
                }
                // Continue listening for messages
                self.receiveMessage()
            }
        }
    }
    
    // Start the listener
    receiveMessage()
    
  5. Handling connection lifecycle events (open, close, errors) using the URLSessionWebSocketDelegate.

    // Example delegate implementation
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Connection opened")
            // Start receiving messages after opening
            receiveMessage() // assuming receiveMessage is defined
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Unknown reason"
            print("Connection closed with code \(closeCode.rawValue), reason: \(reasonString)")
            // Reconnection or termination logic
        }
    
        // Session error handling
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Task completed with error: \(error)")
                // Additional error handling logic
            }
        }
    }
    
    // Use delegate when creating the session
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

I also used third-party libraries such as Starscream when support for older iOS versions or certain features not available in the native solution (e.g., automatic reconnection with exponential backoff) was required. However, if possible, I preferred URLSessionWebSocketTask due to the aforementioned advantages.