WebSocket библиотека Kotlin: Ktor WebSocket
WebSocket — это протокол, обеспечивающий постоянное двунаправленное соединение между клиентом и сервером. В экосистеме Kotlin одной из самых мощных и популярных библиотек для работы с WebSocket является Ktor — асинхронный фреймворк, созданный компанией JetBrains. Ktor предоставляет полноценную поддержку WebSocket как на стороне сервера, так и на стороне клиента, позволяя легко создавать приложения реального времени: чаты, уведомления, онлайн-игры, трекеры данных и многое другое.
В этой статье мы подробно разберём, как использовать WebSocket в Kotlin с помощью Ktor. Вы узнаете, как настроить зависимости, создать WebSocket сервер и клиент, отправлять и получать сообщения, а также обрабатывать ошибки и закрытие соединения.
Установка и настройка
Для начала работы добавьте необходимые зависимости в файл build.gradle.kts (или build.gradle). Если вы используете Gradle, подключите следующие модули:
// build.gradle.kts
dependencies {
// Серверная часть
implementation("io.ktor:ktor-server-core:2.3.0")
implementation("io.ktor:ktor-server-netty:2.3.0")
implementation("io.ktor:ktor-server-websockets:2.3.0")
// Клиентская часть
implementation("io.ktor:ktor-client-core:2.3.0")
implementation("io.ktor:ktor-client-cio:2.3.0")
implementation("io.ktor:ktor-client-websockets:2.3.0")
}
Для Maven используйте аналогичные артефакты. Все модули Ktor версии 2.x.x поддерживают Kotlin Coroutines и работают на JVM, Android, iOS и других платформах.
Создание WebSocket сервера на Ktor
Напишем простой эхо-сервер, который принимает сообщения от клиента и отправляет их обратно. Сервер будет слушать порт 8080.
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.*
fun main() {
embeddedServer(Netty, port = 8080) {
install(WebSockets)
routing {
webSocket("/chat") {
send("Добро пожаловать в чат!")
for (frame in incoming) {
if (frame is Frame.Text) {
val text = frame.readText()
println("Получено: $text")
send("Эхо: $text")
}
}
}
}
}.start(wait = true)
}
В этом примере:
install(WebSockets)— подключает плагин WebSocket к серверу.webSocket("/chat")— определяет endpoint для подключения.send()— отправляет сообщение клиенту.incoming— канал, по которому приходят фреймы от клиента.- Фреймы могут быть текстовыми (
Frame.Text), бинарными (Frame.Binary) или управляющими.
Создание WebSocket клиента на Ktor
Теперь напишем клиент, который подключается к нашему серверу, отправляет приветствие и читает ответы.
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.*
suspend fun main() {
val client = HttpClient(CIO) {
install(WebSockets)
}
client.webSocket("ws://localhost:8080/chat") {
// Читаем приветствие
val welcome = incoming.receive() as Frame.Text
println("Сервер: ${welcome.readText()}")
// Отправляем сообщение
send(Frame.Text("Привет, сервер!"))
// Ждём эхо-ответ
val response = incoming.receive() as Frame.Text
println("Сервер: ${response.readText()}")
// Закрываем соединение
close()
}
client.close()
}
Клиент использует движок CIO (Coroutine-based I/O) — он лёгкий и полностью асинхронный. Обратите внимание на ws:// — для защищённого соединения используйте wss://.
Расширенные возможности
Ktor WebSocket поддерживает не только текстовые, но и бинарные фреймы, пинги/понги, а также работу с сессиями. Вот несколько продвинутых примеров:
1. Обработка бинарных данных
webSocket("/binary") {
for (frame in incoming) {
if (frame is Frame.Binary) {
val bytes = frame.readBytes()
println("Получено ${bytes.size} байт")
send(Frame.Binary(bytes)) // Отправляем обратно
}
}
}