Sobes.tech
Middle

Qual solução você usou para trabalhar com WebSocket?

sobes.tech IA

Resposta da IA

Nos projetos que requeriam interação bidirecional em tempo real, utilizei com sucesso URLSessionWebSocketTask.

Esta é uma solução integrada do framework Network, disponível desde o iOS 13.

Vantagens do URLSessionWebSocketTask:

  • Nativo: Integrado com URLSession, o que simplifica a gestão de conexões e o tratamento de eventos de rede.
  • Performance: Otimizado para trabalhar com a rede ao nível do sistema.
  • Confiabilidade: Mecanismo embutido de pings e pongs, tentativas automáticas de reconexão (embora possa ser necessária lógica adicional para cenários complexos).
  • Segurança: Suporta TLS de série.

Etapas principais:

  1. Criar uma instância de URLSessionWebSocketTask.

    // Criar uma instância de URLSession com configuração padrão
    let session = URLSession(configuration: .default)
    // Inicializar a tarefa WebSocket
    let webSocketTask = session.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    
  2. Iniciar a conexão.

    // Recomeçar a tarefa para estabelecer a conexão
    webSocketTask.resume()
    
  3. Enviar mensagens (texto ou dados binários).

    // Enviar uma mensagem de texto
    webSocketTask.send(.string("Hello, world!")) { error in
        if let error = error {
            print("Erro ao enviar: \(error)")
        }
    }
    
    // Enviar dados binários
    let dataToSend = Data([1, 2, 3])
    webSocketTask.send(.data(dataToSend)) { error in
        if let error = error {
            print("Erro ao enviar: \(error)")
        }
    }
    
  4. Receber mensagens. É um processo assíncrono.

    // Função recursiva para receber mensagens
    func receiveMessage() {
        webSocketTask.receive { result in
            switch result {
            case .failure(let error):
                print("Erro ao receber: \(error)")
                // Lidar com erro, possivelmente tentar reconectar
            case .success(let message):
                switch message {
                case .string(let text):
                    print("Mensagem de texto recebida: \(text)")
                case .data(let data):
                    print("Dados binários recebidos: \(data)")
                @unknown default:
                    fatalError("Tipo de mensagem desconhecido")
                }
                // Continuar ouvindo mensagens
                self.receiveMessage()
            }
        }
    }
    
    // Iniciar ouvindo
    receiveMessage()
    
  5. Gerenciar eventos do ciclo de vida da conexão (abertura, fechamento, erros) usando o delegado URLSessionWebSocketDelegate.

    // Exemplo de implementação do delegado
    class WebSocketHandler: NSObject, URLSessionWebSocketDelegate {
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
            print("Conexão aberta")
            // Iniciar recebimento de mensagens após abertura
            receiveMessage() // Presume-se que receiveMessage está definido
        }
    
        func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
            let reasonString = reason.flatMap { String(data: $0, encoding: .utf8) } ?? "Razão desconhecida"
            print("Conexão fechada com código \(closeCode.rawValue), razão: \(reasonString)")
            // Lógica de reconexão ou encerramento
        }
    
        // Lidar com erros de sessão
        func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
            if let error = error {
                print("Tarefa finalizada com erro: \(error)")
                // Lógica adicional de tratamento de erros
            }
        }
    }
    
    // Ao criar a sessão, usar o delegado
    let delegate = WebSocketHandler()
    let sessionWithDelegate = URLSession(configuration: .default, delegate: delegate, delegateQueue: OperationQueue())
    let webSocketTaskWithDelegate = sessionWithDelegate.webSocketTask(with: URL(string: "wss://example.com/socket")!)
    

Também utilizei bibliotecas de terceiros, como Starscream, quando era necessário suporte para versões mais antigas do iOS ou funcionalidades específicas não disponíveis na solução nativa (por exemplo, reconexão automática com atraso exponencial). No entanto, sempre que possível, preferi URLSessionWebSocketTask devido às vantagens acima mencionadas.