Введение в WebSocket в Kotlin
WebSocket держит одно TCP-соединение открытым после
рукопожатия. Обе стороны могут слать текстовые кадры
в любой момент - без нового HTTP-запроса на каждую
фразу. На JVM для учебных примеров удобна библиотека
Java-WebSocket: классы WebSocketServer и
WebSocketClient из пакета
org.java_websocket.
Сервер слушает адрес с портом 0, после
start номер порта читают у запущенного
экземпляра. Клиент подключается к
ws://127.0.0.1 и этому порту, шлёт строку
на английском; сервер в onMessage может
ответить тем же текстом. Оба конца часто живут в одном
main: сервер в фоне, клиент ждёт ответ через
CountDownLatch, затем соединение закрывают и
вызывают stop у сервера:
import java.net.InetSocketAddress
import java.net.URI
import java.util.concurrent.CountDownLatch
import org.java_websocket.WebSocket
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ClientHandshake
import org.java_websocket.handshake.ServerHandshake
import org.java_websocket.server.WebSocketServer
fun main() {
val ready = CountDownLatch(1)
val done = CountDownLatch(1)
val server = object : WebSocketServer(
InetSocketAddress(0),
) {
override fun onStart() {
ready.countDown()
}
override fun onOpen(
conn: WebSocket,
handshake: ClientHandshake,
) {}
override fun onClose(
conn: WebSocket,
code: Int,
reason: String,
remote: Boolean,
) {}
override fun onMessage(
conn: WebSocket,
message: String,
) {
conn.send(message)
}
override fun onError(
conn: WebSocket,
ex: Exception,
) {}
}
server.start()
ready.await()
val port = server.port
val uri = URI("ws://127.0.0.1:$port")
val client = object : WebSocketClient(uri) {
override fun onOpen(
handshakedata: ServerHandshake,
) {}
override fun onMessage(message: String) {
println(message)
done.countDown()
}
override fun onClose(
code: Int,
reason: String,
remote: Boolean,
) {}
override fun onError(ex: Exception) {}
}
client.connectBlocking()
client.send("hello ws")
done.await()
client.close()
server.stop()
}
В консоли появится строка hello ws - это
ответ сервера на одно отправленное сообщение.
Соединение при этом оставалось открытым между
отправкой и приёмом, что и отличает WebSocket от
разовых HTTP-запросов.