Ktor 2.1.1 Help

Client WebSockets

Ktor supports the WebSocket protocol and allows you to create applications that require real-time data transfer from and to the server. For example, WebSockets can be used to create a chat application.

The Ktor client allows you to handle a WebSocket session for exchanging messages with the server. To learn about WebSocket support in a Ktor server, see Server WebSockets.

Supported engines

The Ktor client supports WebSockets for the following engines:

  • CIO

  • OkHttp

  • Js

  • Darwin

Add dependencies

To use WebSockets, you need to include the ktor-client-websockets artifact in the build script:

implementation("io.ktor:ktor-client-websockets:$ktor_version")
implementation "io.ktor:ktor-client-websockets:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-client-websockets-jvm</artifactId> <version>${ktor_version}</version> </dependency>

You can learn more about artifacts required by the Ktor client from Adding client dependencies.

Install and configure WebSockets

To install the WebSockets plugin, pass it to the install function inside a client configuration block:

import io.ktor.client.* import io.ktor.client.engine.cio.* import io.ktor.client.plugins.websocket.* //... val client = HttpClient(CIO) { install(WebSockets) }

Optionally, you can configure the plugin inside the install block by passing the required options using WebSockets.Config. For instance, you can specify the interval of sending ping frames using the pingInterval property:

val client = HttpClient(CIO) { install(WebSockets) { pingInterval = 20_000 } }

Note that this property is not in effect for the OkHttp engine. You can change the ping interval for OkHttp in the engine configuration:

import io.ktor.client.engine.okhttp.OkHttp val client = HttpClient(OkHttp) { engine { preconfigured = OkHttpClient.Builder() .pingInterval(20, TimeUnit.SECONDS) .build() } }

Handle a WebSockets session

API overview

A client's WebSocket session is represented by the DefaultClientWebSocketSession interface. This interface exposes the API that allows you to send/receive WebSocket frames and close a session. HttpClient allows you to get access to a WebSocket session in one of the following ways:

  • The webSocket function accepts DefaultClientWebSocketSession as a block argument.

    runBlocking { client.webSocket(method = HttpMethod.Get, host = "127.0.0.1", port = 8080, path = "/echo") { // this: DefaultClientWebSocketSession } }
  • The webSocketSession function returns the DefaultClientWebSocketSession instance and allows you to access a session outside the runBlocking or launch scope.

Session configuration might look as follows:

  1. Use the send function to send text content to the server.

  2. Use the incoming and outgoing properties to access the channels for receiving and sending WebSocket frames. A frame is represented by the Frame class.

  3. When handling a session, you can check a frame type, for example:

    • Frame.Text is a text frame. For this frame type, you can read its content using Frame.Text.readText().

    • Frame.Binary is a binary frame. For this type, you can read its content using Frame.Binary.readBytes().

    • Frame.Close is a closing frame. You can call Frame.Close.readReason() to get a close reason for the current session.

  4. Use the close function to send a close frame with the specified reason.

Example

The example below shows how to send a message to the echo WebSocket endpoint and how to receive a response:

fun main() { val client = HttpClient(CIO) { install(WebSockets) { pingInterval = 20_000 } } runBlocking { client.webSocket(method = HttpMethod.Get, host = "127.0.0.1", port = 8080, path = "/echo") { while(true) { val othersMessage = incoming.receive() as? Frame.Text println(othersMessage?.readText()) val myMessage = Scanner(System.`in`).next() if(myMessage != null) { send(myMessage) } } } } client.close() }

You can find the full example here: client-websockets.

Last modified: 16 September 2022