WebSocket client support for Ktor targeting the MinGW x64 platform, enabling native Windows applications built with Kotlin/Native to establish WebSocket connections.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Ktor WebSocket client plugin for MinGW x64 platform, enabling native Windows applications built with Kotlin/Native to establish WebSocket connections. This plugin provides complete WebSocket client functionality including bidirectional communication, message serialization, connection lifecycle management, and ping/pong support for connection health monitoring.
implementation("io.ktor:ktor-client-websockets-mingwx64:3.2.0")import io.ktor.client.*
import io.ktor.client.plugins.websocket.*For WebSocket frames and session types:
import io.ktor.websocket.*For serialization support:
import io.ktor.websocket.serialization.*import io.ktor.client.*
import io.ktor.client.engine.winhttp.*
import io.ktor.client.plugins.websocket.*
import io.ktor.websocket.*
// Create client with WebSocket plugin
val client = HttpClient(WinHttp) {
install(WebSockets) {
pingInterval = 30.seconds
maxFrameSize = 1024 * 1024 // 1MB
}
}
// Connect and use WebSocket
client.webSocket(
method = HttpMethod.Get,
host = "echo.websocket.org",
port = 80,
path = "/"
) {
// Send text message
send(Frame.Text("Hello WebSocket!"))
// Receive message
for (frame in incoming) {
when (frame) {
is Frame.Text -> {
val message = frame.readText()
println("Received: $message")
}
is Frame.Binary -> {
val data = frame.readBytes()
println("Received binary data: ${data.size} bytes")
}
is Frame.Close -> {
println("Connection closed")
break
}
else -> {}
}
}
}
client.close()The Ktor WebSocket client plugin integrates with the Ktor HTTP client framework through several key components:
Install and configure the WebSocket plugin for your HttpClient instance.
fun HttpClientConfig<*>.WebSockets(config: WebSockets.Config.() -> Unit)
class WebSockets {
constructor()
constructor(pingIntervalMillis: Long, maxFrameSize: Long)
constructor(
pingIntervalMillis: Long,
maxFrameSize: Long,
extensionsConfig: WebSocketExtensionsConfig,
contentConverter: WebsocketContentConverter? = null
)
val pingIntervalMillis: Long
val maxFrameSize: Long
val contentConverter: WebsocketContentConverter?
}
fun WebSockets(
pingInterval: Duration?,
maxFrameSize: Long = Int.MAX_VALUE.toLong()
): WebSockets
class WebSockets.Config {
var pingIntervalMillis: Long
var maxFrameSize: Long
var pingInterval: Duration?
var contentConverter: WebsocketContentConverter?
fun extensions(block: WebSocketExtensionsConfig.() -> Unit)
}Create WebSocket connections using various methods - session-based for manual management or block-based for automatic cleanup.
suspend fun HttpClient.webSocketSession(
block: HttpRequestBuilder.() -> Unit
): DefaultClientWebSocketSession
suspend fun HttpClient.webSocketSession(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
block: HttpRequestBuilder.() -> Unit = {}
): DefaultClientWebSocketSession
suspend fun HttpClient.webSocketSession(
urlString: String,
block: HttpRequestBuilder.() -> Unit = {}
): DefaultClientWebSocketSession
suspend fun HttpClient.webSocket(
request: HttpRequestBuilder.() -> Unit,
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.webSocket(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.webSocket(
urlString: String,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)Establish secure WebSocket connections over SSL/TLS using the WSS protocol.
suspend fun HttpClient.wss(
request: HttpRequestBuilder.() -> Unit,
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.wss(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.wss(
urlString: String,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)Shorthand functions for WebSocket connections - ws aliases for standard connections.
suspend fun HttpClient.ws(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.ws(
request: HttpRequestBuilder.() -> Unit,
block: suspend DefaultClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.ws(
urlString: String,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)Client-specific WebSocket session interfaces providing access to the underlying HTTP call and session management.
interface ClientWebSocketSession : WebSocketSession {
val call: HttpClientCall
}
open class DefaultClientWebSocketSession(
override val call: HttpClientCall,
delegate: DefaultWebSocketSession
) : ClientWebSocketSession, DefaultWebSocketSession
val DefaultClientWebSocketSession.converter: WebsocketContentConverter?Automatic serialization and deserialization of custom types using configured content converters.
suspend fun DefaultClientWebSocketSession.sendSerialized(
data: Any?,
typeInfo: TypeInfo
)
suspend inline fun <reified T> DefaultClientWebSocketSession.sendSerialized(
data: T
)
suspend fun <T> DefaultClientWebSocketSession.receiveDeserialized(
typeInfo: TypeInfo
): T
suspend inline fun <reified T> DefaultClientWebSocketSession.receiveDeserialized(): T
interface WebsocketContentConverter {
suspend fun serialize(
charset: Charset,
typeInfo: TypeInfo,
value: Any?
): Frame
suspend fun deserialize(
charset: Charset,
typeInfo: TypeInfo,
content: Frame
): Any?
fun isApplicable(frame: Frame): Boolean
}
suspend inline fun <reified T> WebsocketContentConverter.serialize(
value: T,
charset: Charset = Charsets.UTF_8
): Frame
suspend inline fun <reified T> WebsocketContentConverter.deserialize(
content: Frame,
charset: Charset = Charsets.UTF_8
): TCapability indicators for WebSocket support in HTTP client engines.
object WebSocketCapability : HttpClientEngineCapability<Unit>
object WebSocketExtensionsCapability : HttpClientEngineCapability<Unit>WebSocket-specific exception types for error handling.
class WebSocketException(message: String, cause: Throwable?) : IllegalStateException {
constructor(message: String)
}
open class WebsocketContentConvertException(
message: String,
cause: Throwable? = null
) : ContentConvertException
class WebsocketConverterNotFoundException(
message: String,
cause: Throwable? = null
) : WebsocketContentConvertException
class WebsocketDeserializeException(
message: String,
cause: Throwable? = null,
val frame: Frame
) : WebsocketContentConvertExceptionImportant constants used in WebSocket configuration.
const val PINGER_DISABLED: Long = 0Base WebSocket session interface from the shared websocket module.
interface WebSocketSession : CoroutineScope {
var masking: Boolean
var maxFrameSize: Long
val incoming: ReceiveChannel<Frame>
val outgoing: SendChannel<Frame>
val extensions: List<WebSocketExtension<*>>
suspend fun send(frame: Frame)
suspend fun flush()
}
class DefaultWebSocketSession : WebSocketSessionFrame types for different kinds of WebSocket messages.
sealed class Frame {
class Text(val data: ByteArray) : Frame {
constructor(text: String)
fun readText(): String
}
class Binary(val data: ByteArray) : Frame {
fun readBytes(): ByteArray
}
class Close(val data: ByteArray) : Frame {
constructor(reason: CloseReason?)
fun readReason(): CloseReason?
}
class Ping(val data: ByteArray) : Frame {
constructor()
}
class Pong(val data: ByteArray) : Frame {
constructor()
}
}
data class CloseReason(val code: Short, val message: String)Extension mechanism for WebSocket protocol extensions.
interface WebSocketExtension<ConfigType : Any> {
val factory: WebSocketExtensionFactory<ConfigType, out WebSocketExtension<ConfigType>>
val protocols: List<WebSocketExtensionHeader>
fun clientNegotiation(negotiatedProtocols: List<WebSocketExtensionHeader>): Boolean
fun serverNegotiation(requestedProtocols: List<WebSocketExtensionHeader>): List<WebSocketExtensionHeader>
fun processOutgoingFrame(frame: Frame): Frame
fun processIncomingFrame(frame: Frame): Frame
}
interface WebSocketExtensionFactory<ConfigType : Any, ExtensionType : WebSocketExtension<ConfigType>> {
val key: AttributeKey<ExtensionType>
val rsv1: Boolean
val rsv2: Boolean
val rsv3: Boolean
fun install(config: ConfigType.() -> Unit): ExtensionType
}
class WebSocketExtensionsConfig {
fun <ConfigType : Any> install(
extension: WebSocketExtensionFactory<ConfigType, *>,
config: ConfigType.() -> Unit = {}
)
fun build(): List<WebSocketExtension<*>>
}client.webSocket("wss://echo.websocket.org") {
// Send text message
send(Frame.Text("Hello WebSocket!"))
// Read response
val response = incoming.receive()
if (response is Frame.Text) {
println("Echo: ${response.readText()}")
}
}client.webSocket(host = "example.com", port = 8080, path = "/websocket") {
// Send binary data
val binaryData = byteArrayOf(1, 2, 3, 4, 5)
send(Frame.Binary(binaryData))
// Receive binary response
for (frame in incoming) {
when (frame) {
is Frame.Binary -> {
val receivedData = frame.readBytes()
println("Received ${receivedData.size} bytes")
}
is Frame.Close -> break
else -> {}
}
}
}val client = HttpClient(WinHttp) {
install(WebSockets) {
pingInterval = 30.seconds // Send ping every 30 seconds
maxFrameSize = 1024 * 1024 // 1MB max frame size
}
}
client.webSocket("wss://example.com/websocket") {
// Ping frames are sent automatically
// Connection will be kept alive with ping/pong
for (frame in incoming) {
when (frame) {
is Frame.Text -> {
println("Message: ${frame.readText()}")
}
is Frame.Ping -> {
// Pong is sent automatically
println("Ping received")
}
is Frame.Pong -> {
println("Pong received")
}
is Frame.Close -> {
println("Connection closed: ${frame.readReason()}")
break
}
else -> {}
}
}
}// Configure serialization
val client = HttpClient(WinHttp) {
install(WebSockets) {
contentConverter = KotlinxWebsocketSerializationConverter(Json)
}
}
client.webSocket("wss://api.example.com/websocket") {
// Send serialized object
sendSerialized(UserMessage("Hello", "user123"))
// Receive and deserialize
val response = receiveDeserialized<ServerResponse>()
println("Received: ${response.message}")
}try {
client.webSocket("wss://unreachable.example.com") {
send(Frame.Text("Hello"))
}
} catch (e: WebSocketException) {
println("WebSocket error: ${e.message}")
} catch (e: ConnectTimeoutException) {
println("Connection timeout")
} catch (e: Exception) {
println("General error: ${e.message}")
}pkg:gradle/io.ktor/ktor-client-websockets-mingwx64@3.2.x