Skip to content
advanced Phase 5 · Networking & Data

WebSockets

Implement real-time communication with URLSessionWebSocketTask for live data updates.

50m
3 problems
Topic Progress 0%

WebSocket Protocol

What are WebSockets?

WebSockets provide full-duplex communication over a single TCP connection. Unlike HTTP request-response, WebSockets allow both the client and server to send messages at any time.

This makes WebSockets ideal for real-time features like chat apps, live dashboards, multiplayer games, and collaborative editing.

WebSocket Handshake

WebSockets start as HTTP requests with an upgrade header:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

If the server supports WebSockets, it responds with 101 Switching Protocols.

Use Cases

WebSockets are perfect for:

  • Real-time chat and messaging
  • Live sports scores and financial data
  • Multiplayer game state synchronization
  • Collaborative document editing
  • Live notifications and alerts
  • IoT device communication

When NOT to Use WebSockets

Avoid WebSockets when:

  • You need simple request-response patterns (use REST)
  • Data is rarely updated (use polling or push notifications)
  • You need automatic scaling (WebSockets maintain state)
  • Mobile data usage is a concern (persistent connections)

URLSessionWebSocketTask

Creating a WebSocket Task

iOS provides URLSessionWebSocketTask for WebSocket communication:

let url = URL(string: "wss://echo.websocket.org")!
let session = URLSession(configuration: .default)
let task = session.webSocketTask(with: url)

Connecting

task.resume()
print("WebSocket connected")

Receiving Messages

func receiveMessages() async {
    do {
        let message = try await task.receive()
        switch message {
        case .string(let text):
            print("Text: \(text)")
        case .data(let data):
            print("Data: \(data.count) bytes")
        @unknown default:
            break
        }
    } catch {
        print("Receive error: \(error)")
    }
}

// Listen for messages in a loop
func listenForMessages() async {
    while task.state == .running {
        await receiveMessages()
    }
}

Sending Messages

// Send text
let message = URLSessionWebSocketTask.Message.string("Hello Server")
task.send(message) { error in
    if let error = error {
        print("Send error: \(error)")
    }
}

// Send data
let jsonData = try JSONEncoder().encode(ChatMessage(text: "Hello"))
task.send(.data(jsonData)) { error in
    if let error = error {
        print("Send error: \(error)")
    }
}

Ping/Pong Keepalive

task.sendPing { error in
    if let error = error {
        print("Ping failed: \(error)")
    } else {
        print("Pong received")
    }
}

Disconnecting

task.cancel(with: .goingAway, reason: nil)

Real-Time Communication

WebSocket Manager

Create a reusable WebSocket manager:

actor WebSocketManager {
    private var task: URLSessionWebSocketTask?
    private let session: URLSession
    private var url: URL
    
    init(url: URL) {
        self.url = url
        self.session = URLSession(configuration: .default)
    }
    
    func connect() async throws {
        task = session.webSocketTask(with: url)
        task?.resume()
    }
    
    func send(_ message: String) async throws {
        try await task?.send(.string(message))
    }
    
    func receive() async throws -> String {
        let message = try await task?.receive()
        switch message {
        case .string(let text): return text
        case .data(let data): return String(data: data, encoding: .utf8) ?? ""
        default: return ""
        }
    }
    
    func disconnect() {
        task?.cancel(with: .goingAway, reason: nil)
    }
}

Reconnection Logic

Implement automatic reconnection with exponential backoff:

func connectWithReconnect() async {
    var attempt = 0
    let maxAttempts = 10
    
    while attempt < maxAttempts {
        do {
            try await connect()
            await listenForMessages()
            return
        } catch {
            attempt += 1
            let delay = min(pow(2.0, Double(attempt)), 30.0)
            try? await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000))
        }
    }
}

Message Protocol

Define a message protocol for type safety:

enum ChatMessage: Codable {
    case text(String)
    case userJoined(String)
    case userLeft(String)
    case typing(String)
}

Handling Disconnections

Detect and handle disconnections:

func listenForMessages() async {
    while task?.state == .running {
        do {
            let message = try await task?.receive()
            // Process message
        } catch {
            // Connection lost - attempt reconnect
            await connectWithReconnect()
            return
        }
    }
}

Quiz

1. What protocol upgrade starts a WebSocket connection?

Question 1 options

2. What does URLSessionWebSocketTask.receive() return?

Question 2 options

3. What is ping/pong used for in WebSockets?

Question 3 options

4. How do you close a WebSocket connection gracefully?

Question 4 options

Flashcards

Question

What is a WebSocket?

Answer

A protocol for full-duplex communication over a single TCP connection, allowing both client and server to send messages at any time.

Question

How do you create a WebSocket connection in iOS?

Answer

Use URLSession.webSocketTask(with: url) to create a task, then call .resume() to connect.

Question

What message types do WebSockets support?

Answer

Text frames (strings) and binary frames (Data). URLSessionWebSocketTask.Message has .string and .data cases.

Question

When should you use WebSockets vs REST?

Answer

Use WebSockets for real-time bidirectional communication. Use REST for simple request-response patterns.

Revision Notes

Key Takeaways

  • 1. WebSockets provide full-duplex communication for real-time features
  • 2. URLSessionWebSocketTask handles WebSocket connections on iOS
  • 3. Ping/pong frames maintain connection health
  • 4. Implement reconnection with exponential backoff for reliability
  • 5. Use WebSockets for chat, live data, and collaborative features

Interview Tips

  • Explain the WebSocket handshake process (HTTP Upgrade to 101)
  • Know when to use WebSockets vs Server-Sent Events vs REST
  • Describe reconnection strategies with exponential backoff
  • Discuss handling message ordering and delivery guarantees

Cheat Sheet

WebSockets: Full-duplex over single TCP connection.
URLSessionWebSocketTask: .resume() to connect, .receive() for messages, .send() to send.
Ping/Pong: Keepalive mechanism to detect dead connections.
Reconnection: Exponential backoff (1s, 2s, 4s) with max attempts.
Disconnect: .cancel(with: .goingAway, reason: nil).