Regardless of the server, I get ClosedReceiveChannelException about 1 minute after startup for unknown reason. What am i doing wrong?
Code:
val client = HttpClient(CIO) {
install(WebSockets)
}
// Coroutine Scope
client.webSocket(host = "ws.ifelse.io") {
try {
while (true) {
val rawPayload = incoming.receive() as? Frame.Text ?: continue
println(rawPayload.readText())
}
} catch (e: Exception) {
log.error("Caused unexpected exception while receiving payload:\n${e.stackTraceToString()}")
client.close()
}
}
Error:
kotlinx.coroutines.channels.ClosedReceiveChannelException: Channel was closed
at kotlinx.coroutines.channels.Closed.getReceiveException(AbstractChannel.kt:1141)
at kotlinx.coroutines.channels.AbstractChannel$ReceiveElement.resumeReceiveClosed(AbstractChannel.kt:938)
at A really long call stack that prevents me from posting the question, but if necessary I can post the whole error.
CodePudding user response:
I would recommend having a look at Ktor's Server WebSocket documentation.
- Make sure you have the required dependencies installed. In this case:
implementation("io.ktor:ktor-websockets:$ktor_version")
- Try installing the WebSocket like this:
import io.ktor.features.*
// ...
fun Application.module() {
install(WebSockets)
// ...
}
or
import io.ktor.features.*
// ...
fun main() {
embeddedServer(Netty, port = 8080) {
install(WebSockets)
// ...
}.start(wait = true)
}
- Make sure your WebSocket configuration is correct:
install(WebSockets) {
pingPeriod = Duration.ofSeconds(15)
timeout = Duration.ofSeconds(15)
maxFrameSize = Long.MAX_VALUE
masking = false
}
- A
while(true)
call in this case is not necessary. You can accomplish the same thing by doing something like this:
routing {
webSocket("/echo") {
send("Please enter your name")
for (frame in incoming) {
when (frame) {
is Frame.Text -> {
val receivedText = frame.readText()
if (receivedText.equals("bye", ignoreCase = true)) close(CloseReason(CloseReason.Codes.NORMAL, "Client said BYE"))
else send(Frame.Text("Hi, $receivedText!"))
}
}
}
}
}
}
CodePudding user response:
Solved. Setting pingInterval in the client config solved the problem. Final code:
val client = HttpClient(CIO) {
install(WebSockets) {
pingInterval = 500
}
}
// Coroutine Scope
client.webSocket("ws.ifelse.io") {
try {
for (frame in incoming) {
frame as? Frame.Text ?: continue
println(frame.readText())
}
} catch (e: Exception) {
log.error("Caused unexpected exception while receiving payload:\n${e.stackTraceToString()}")
client.close()
}
}