0
# Session Management
1
2
WebSocket session interfaces providing frame-level control, connection lifecycle management, and extension support for real-time bidirectional communication.
3
4
## Capabilities
5
6
### Client WebSocket Session Interface
7
8
Base interface for client-specific WebSocket sessions with access to the underlying HTTP call.
9
10
```kotlin { .api }
11
/**
12
* Client specific WebSocket session interface
13
* Extends WebSocketSession with client-specific functionality
14
*/
15
interface ClientWebSocketSession : WebSocketSession {
16
/** HttpClientCall associated with this WebSocket session */
17
val call: HttpClientCall
18
}
19
```
20
21
### Default Client WebSocket Session
22
23
Default implementation of client WebSocket session with full feature support.
24
25
```kotlin { .api }
26
/**
27
* Default implementation of ClientWebSocketSession
28
* Provides complete WebSocket functionality with ping/pong support
29
* @param call HttpClientCall associated with session
30
* @param delegate Underlying DefaultWebSocketSession implementation
31
*/
32
class DefaultClientWebSocketSession(
33
override val call: HttpClientCall,
34
delegate: DefaultWebSocketSession
35
) : ClientWebSocketSession, DefaultWebSocketSession by delegate
36
```
37
38
### Base WebSocket Session Interface
39
40
Core WebSocket session interface providing frame communication and lifecycle management.
41
42
```kotlin { .api }
43
/**
44
* Base WebSocket session interface for bidirectional communication
45
* Extends CoroutineScope for structured concurrency support
46
*/
47
interface WebSocketSession : CoroutineScope {
48
/** Enable/disable masking of outgoing messages with random XOR mask */
49
var masking: Boolean
50
51
/** Frame size limit - connection closed if exceeded */
52
var maxFrameSize: Long
53
54
/** Channel for receiving incoming WebSocket frames */
55
val incoming: ReceiveChannel<Frame>
56
57
/** Channel for sending outgoing WebSocket frames */
58
val outgoing: SendChannel<Frame>
59
60
/** List of installed WebSocket extensions */
61
val extensions: List<WebSocketExtension<*>>
62
}
63
```
64
65
**Usage Examples:**
66
67
```kotlin
68
client.webSocket("ws://echo.websocket.org") {
69
// Configure session properties
70
maxFrameSize = 1024 * 1024 // 1MB limit
71
masking = true
72
73
// Send frames through outgoing channel
74
outgoing.send(Frame.Text("Hello WebSocket!"))
75
76
// Receive frames from incoming channel
77
for (frame in incoming) {
78
when (frame) {
79
is Frame.Text -> println("Text: ${frame.readText()}")
80
is Frame.Binary -> println("Binary: ${frame.data.size} bytes")
81
is Frame.Close -> break
82
}
83
}
84
}
85
```
86
87
### Default WebSocket Session Interface
88
89
Extended WebSocket session with ping/pong functionality and timeout handling.
90
91
```kotlin { .api }
92
/**
93
* Default WebSocket session with ping/pong support
94
* Provides automatic keep-alive functionality
95
*/
96
interface DefaultWebSocketSession : WebSocketSession {
97
/** Interval between ping messages in milliseconds */
98
val pingIntervalMillis: Long
99
100
/** Timeout for ping/pong roundtrip in milliseconds */
101
val timeoutMillis: Long
102
}
103
104
/**
105
* Create DefaultWebSocketSession with ping/pong configuration
106
* @param session Underlying WebSocket session
107
* @param pingIntervalMillis Ping interval in milliseconds
108
* @param timeoutMillis Ping timeout in milliseconds
109
* @return Configured DefaultWebSocketSession
110
*/
111
fun DefaultWebSocketSession(
112
session: WebSocketSession,
113
pingIntervalMillis: Long,
114
timeoutMillis: Long = pingIntervalMillis * 2
115
): DefaultWebSocketSession
116
```
117
118
### Session Extension Functions
119
120
Utility functions for working with WebSocket extensions.
121
122
```kotlin { .api }
123
/**
124
* Get WebSocket extension instance by factory
125
* @param extension Extension factory to look up
126
* @return Extension instance
127
* @throws NoSuchElementException if extension not found
128
*/
129
fun <T : WebSocketExtension<*>> WebSocketSession.extension(
130
extension: WebSocketExtensionFactory<*, T>
131
): T
132
133
/**
134
* Get WebSocket extension instance by factory, or null if not found
135
* @param extension Extension factory to look up
136
* @return Extension instance or null
137
*/
138
fun <T : WebSocketExtension<*>> WebSocketSession.extensionOrNull(
139
extension: WebSocketExtensionFactory<*, T>
140
): T?
141
142
/**
143
* Send text message as Text frame
144
* @param content Text content to send
145
*/
146
suspend fun WebSocketSession.send(content: String)
147
148
/**
149
* Send binary data as Binary frame
150
* @param content Binary data to send
151
*/
152
suspend fun WebSocketSession.send(content: ByteArray)
153
154
/**
155
* Send WebSocket frame
156
* @param frame Frame to send
157
*/
158
suspend fun WebSocketSession.send(frame: Frame)
159
```
160
161
**Usage Examples:**
162
163
```kotlin
164
client.webSocket("ws://example.com") {
165
// Check if compression extension is available
166
val deflate = extensionOrNull(WebSocketDeflateExtension)
167
if (deflate != null) {
168
println("Using compression: ${deflate.compressionLevel}")
169
}
170
171
// Get required extension (throws if not found)
172
try {
173
val customExt = extension(CustomWebSocketExtension)
174
customExt.configure()
175
} catch (e: NoSuchElementException) {
176
println("Custom extension not available")
177
}
178
}
179
```
180
181
## Session Management Examples
182
183
### Basic Session Usage
184
185
```kotlin
186
client.webSocket("ws://echo.websocket.org") {
187
// Session is DefaultClientWebSocketSession
188
println("Connected to: ${call.request.url}")
189
println("Max frame size: $maxFrameSize")
190
191
// Send text message
192
send("Hello!")
193
194
// Process incoming messages
195
for (frame in incoming) {
196
when (frame) {
197
is Frame.Text -> {
198
val text = frame.readText()
199
println("Received: $text")
200
if (text == "bye") break
201
}
202
is Frame.Close -> {
203
println("Connection closed")
204
break
205
}
206
}
207
}
208
}
209
```
210
211
### Manual Session Management
212
213
```kotlin
214
val session = client.webSocketSession("ws://api.example.com/ws")
215
216
try {
217
// Configure session
218
session.maxFrameSize = 512 * 1024
219
220
// Send initial message
221
session.outgoing.send(Frame.Text("CONNECT"))
222
223
// Handle responses
224
while (!session.incoming.isClosedForReceive) {
225
val frame = session.incoming.receiveCatching().getOrNull() ?: break
226
227
when (frame) {
228
is Frame.Text -> processMessage(frame.readText())
229
is Frame.Binary -> processBinary(frame.data)
230
is Frame.Ping -> session.outgoing.send(Frame.Pong(frame.data))
231
is Frame.Close -> break
232
}
233
}
234
} finally {
235
session.close()
236
}
237
```
238
239
### Session with Ping/Pong Monitoring
240
241
```kotlin
242
client.webSocket("ws://api.example.com/realtime") {
243
println("Ping interval: ${pingIntervalMillis}ms")
244
println("Timeout: ${timeoutMillis}ms")
245
246
// Monitor connection health
247
launch {
248
while (isActive) {
249
delay(5000) // Check every 5 seconds
250
if (incoming.isClosedForReceive) {
251
println("Connection lost")
252
break
253
}
254
}
255
}
256
257
// Handle messages
258
for (frame in incoming) {
259
when (frame) {
260
is Frame.Text -> handleMessage(frame.readText())
261
is Frame.Ping -> {
262
println("Received ping")
263
// Pong is sent automatically
264
}
265
is Frame.Pong -> println("Received pong")
266
is Frame.Close -> {
267
val reason = frame.readReason()
268
println("Connection closed: ${reason?.message}")
269
break
270
}
271
}
272
}
273
}
274
```
275
276
### Concurrent Send and Receive
277
278
```kotlin
279
client.webSocket("ws://chat.example.com") {
280
// Separate coroutines for sending and receiving
281
val sendJob = launch {
282
while (isActive) {
283
val message = readLine() ?: break
284
outgoing.send(Frame.Text(message))
285
}
286
}
287
288
val receiveJob = launch {
289
for (frame in incoming) {
290
when (frame) {
291
is Frame.Text -> println(">> ${frame.readText()}")
292
is Frame.Close -> break
293
}
294
}
295
}
296
297
// Wait for either job to complete
298
select {
299
sendJob.onJoin { println("Send completed") }
300
receiveJob.onJoin { println("Receive completed") }
301
}
302
303
// Cancel remaining job
304
sendJob.cancel()
305
receiveJob.cancel()
306
}
307
```
308
309
### Extension Management
310
311
```kotlin
312
client.webSocket("ws://api.example.com") {
313
// List all active extensions
314
println("Active extensions:")
315
extensions.forEach { ext ->
316
println("- ${ext::class.simpleName}")
317
}
318
319
// Check for specific extension
320
extensionOrNull(WebSocketDeflateExtension)?.let { deflate ->
321
println("Compression enabled: level ${deflate.compressionLevel}")
322
}
323
324
// Session logic continues...
325
}
326
```
327
328
### Error Handling in Sessions
329
330
```kotlin
331
try {
332
client.webSocket("ws://unreliable.example.com") {
333
// Configure larger timeout for unreliable connection
334
maxFrameSize = 2 * 1024 * 1024 // 2MB
335
336
for (frame in incoming) {
337
try {
338
when (frame) {
339
is Frame.Text -> processText(frame.readText())
340
is Frame.Binary -> processBinary(frame.data)
341
}
342
} catch (e: Exception) {
343
println("Frame processing error: ${e.message}")
344
// Continue processing other frames
345
}
346
}
347
}
348
} catch (e: WebSocketException) {
349
println("WebSocket error: ${e.message}")
350
} catch (e: ProtocolViolationException) {
351
println("Protocol violation: ${e.message}")
352
}
353
```