CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-websockets

Ktor client WebSocket plugin - provides WebSocket support for the Ktor HTTP client on multiple platforms including iOS x64

Pending
Overview
Eval results
Files

session-operations.mddocs/

Session Operations

WebSocket session operations provide access to client-specific session interfaces, HTTP call context, and core frame communication functionality.

Client WebSocket Session Interface

The main interface for client WebSocket sessions that provides access to the associated HTTP call:

interface ClientWebSocketSession : WebSocketSession {
    val call: HttpClientCall
}
  • call: Access to the original HttpClientCall that initiated the WebSocket connection
  • Inherits: All functionality from WebSocketSession (masking, frame size, channels, extensions)

Usage:

client.webSocketSession("ws://example.com/") { session ->
    // Access HTTP call context
    println("Request URL: ${session.call.request.url}")
    println("Response status: ${session.call.response.status}")
    
    // Use WebSocket functionality
    session.send("Hello!")
}

Default Client WebSocket Session

The default implementation used by all WebSocket connection functions:

class DefaultClientWebSocketSession(
    override val call: HttpClientCall,
    delegate: DefaultWebSocketSession
) : ClientWebSocketSession, DefaultWebSocketSession by delegate
  • Delegation: Delegates WebSocket functionality to DefaultWebSocketSession
  • HTTP Context: Maintains reference to the originating HTTP call
  • Ping-Pong: Supports automatic ping-pong heartbeat mechanism

Properties inherited from WebSocketSession:

var masking: Boolean                        // Frame masking (client-side typically true)
var maxFrameSize: Long                     // Maximum frame size limit
val incoming: ReceiveChannel<Frame>        // Channel for incoming frames
val outgoing: SendChannel<Frame>           // Channel for outgoing frames
val extensions: List<WebSocketExtension<*>> // Active WebSocket extensions

Properties inherited from DefaultWebSocketSession:

var pingIntervalMillis: Long               // Ping interval in milliseconds
var timeoutMillis: Long                    // Session timeout in milliseconds
val closeReason: Deferred<CloseReason?>    // Deferred close reason

Frame Communication

Sending Frames

Send different types of WebSocket frames:

client.webSocket("ws://example.com/") {
    // Send text frame (convenience method)
    send("Hello WebSocket!")
    
    // Send explicit text frame
    send(Frame.Text("Explicit text frame"))
    
    // Send binary frame
    val data = "Binary data".toByteArray()
    send(Frame.Binary(true, data))
    
    // Send ping frame
    send(Frame.Ping("ping-data".toByteArray()))
    
    // Send pong frame (usually automatic)
    send(Frame.Pong("pong-data".toByteArray()))
    
    // Send close frame
    send(Frame.Close(CloseReason(CloseReason.Codes.NORMAL, "Goodbye")))
}

Receiving Frames

Process incoming WebSocket frames:

client.webSocket("ws://example.com/") {
    // Receive single frame
    val frame = incoming.receive()
    when (frame) {
        is Frame.Text -> {
            val text = frame.readText()
            println("Text: $text")
        }
        is Frame.Binary -> {
            val data = frame.data
            println("Binary: ${data.size} bytes")
        }
        is Frame.Close -> {
            val reason = frame.readReason()
            println("Close: ${reason?.code} - ${reason?.message}")
        }
        is Frame.Ping -> {
            println("Ping received")
            // Pong response usually automatic
        }
        is Frame.Pong -> {
            println("Pong received")
        }
    }
    
    // Process all incoming frames
    for (frame in incoming) {
        when (frame) {
            is Frame.Text -> handleTextFrame(frame.readText())
            is Frame.Binary -> handleBinaryFrame(frame.data)
            is Frame.Close -> {
                println("Connection closed: ${frame.readReason()}")
                break
            }
            else -> println("Other frame: $frame")
        }
    }
}

Frame Utilities

Convenience methods for working with frames:

// Text frame utilities
fun Frame.Text.readText(): String          // Read frame content as text

// Binary frame utilities  
val Frame.Binary.data: ByteArray           // Access binary data

// Close frame utilities
fun Frame.Close.readReason(): CloseReason? // Read close reason

Session Management

Manual Session Management

Create and manage sessions manually:

val session = client.webSocketSession("ws://example.com/")

try {
    // Use session
    session.send("Hello!")
    val response = session.incoming.receive()
    println("Response: $response")
} finally {
    // Always close manually created sessions
    session.close(CloseReason(CloseReason.Codes.NORMAL, "Done"))
}

Automatic Session Management

Use session blocks for automatic management:

client.webSocket("ws://example.com/") {
    // Session automatically closed when block exits
    send("Hello!")
    val response = incoming.receive()
    println("Response: $response")
    
    // Explicit close optional
    close(CloseReason(CloseReason.Codes.NORMAL, "Finished"))
}

Session Properties and Methods

Core WebSocket Methods

suspend fun WebSocketSession.send(frame: Frame)
suspend fun WebSocketSession.flush()
suspend fun WebSocketSession.close(reason: CloseReason? = null)

Ping-Pong Control

var DefaultWebSocketSession.pingIntervalMillis: Long  // Ping interval
var DefaultWebSocketSession.timeoutMillis: Long       // Timeout for responses
val DefaultWebSocketSession.closeReason: Deferred<CloseReason?> // Final close reason

Usage:

client.webSocket("ws://example.com/") {
    // Configure ping behavior
    pingIntervalMillis = 30_000  // 30 seconds
    timeoutMillis = 60_000       // 60 seconds timeout
    
    send("Configured connection!")
    
    // Wait for close reason
    val reason = closeReason.await()
    println("Session closed: $reason")
}

Error Handling in Sessions

Handle session-level errors and exceptions:

client.webSocket("ws://example.com/") {
    try {
        send("Test message")
        
        for (frame in incoming) {
            when (frame) {
                is Frame.Text -> processMessage(frame.readText())
                is Frame.Close -> {
                    val reason = frame.readReason()
                    if (reason?.code != CloseReason.Codes.NORMAL.code) {
                        println("Abnormal close: ${reason?.message}")
                    }
                    break
                }
                else -> { /* Handle other frames */ }
            }
        }
    } catch (e: ClosedReceiveChannelException) {
        println("Connection closed unexpectedly")
    } catch (e: WebSocketException) {
        println("WebSocket error: ${e.message}")
    } catch (e: Exception) {
        println("Session error: ${e.message}")
        // Close gracefully on error
        close(CloseReason(CloseReason.Codes.INTERNAL_ERROR, "Client error"))
    }
}

Content Converter Access

Access the configured content converter for serialization:

val DefaultClientWebSocketSession.converter: WebsocketContentConverter?

Usage:

client.webSocket("ws://example.com/") {
    val converter = this.converter
    if (converter != null) {
        println("Content converter available: ${converter::class.simpleName}")
        // Use sendSerialized/receiveDeserialized
    } else {
        println("No content converter configured")
        // Use raw frame operations
    }
}

Session Lifecycle

  1. Creation: Session created during WebSocket handshake
  2. Initialization: ping-pong timers started (if configured)
  3. Active Communication: Frame exchange through incoming/outgoing channels
  4. Heartbeat: Automatic ping frames sent based on pingIntervalMillis
  5. Timeout Detection: Session terminated if no pong received within timeoutMillis
  6. Graceful Close: Close frame exchange with reason code
  7. Resource Cleanup: Channels closed, timers cancelled, HTTP call completed

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-websockets

docs

content-serialization.md

index.md

plugin-configuration.md

raw-websocket-operations.md

session-operations.md

websocket-connections.md

tile.json