ktorio / ktorio/ktor

How to disable forcibly closed by the remote host?

Open
#1,801 2 comments 0 reactions 1 assignee Claimed by @e5l View on GitHub
bug
Dominant language
Kotlin
Stars
14.5k
Forks
1.3k
Avg merge
2d 13h
Merged PRs (30d)
49

Description

**Ktor Version and Engine Used (client or server and name)**
`implementation "io.ktor:ktor-network:1.3.2"`

**Describe the bug**
Using the raw socket example. My existing client (untouchable) is having a duplication connection which is a known issue on client side. But the server is forcibly closing the client connection. I've added some custom socket options to keep alive but it does not work. The coroutine is cancelling when there is an existing connection

```
/**
* Set TCP_KEEP_ALIVE socket option to enable the Nagle algorithm.
*/
private fun > T.tcpKeepAlive(): T {
return configure {
if (this is SocketOptions.TCPClientSocketOptions) {
keepAlive = true
}
}
}
```

**To Reproduce**
Simple echo server example from https://ktor.io/servers/raw-sockets.html

```
fun main(args: Array) {
runBlocking {
val server = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().bind(InetSocketAddress("127.0.0.1", 2323))
println("Started echo telnet server at ${server.localAddress}")

while (true) {
val socket = server.accept()

launch {
println("Socket accepted: ${socket.remoteAddress}")

val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)

try {
while (true) {
val line = input.readUTF8Line()

println("${socket.remoteAddress}: $line")
output.write("$line\r\n")
}
} catch (e: Throwable) {
e.printStackTrace()
socket.close()
}
}
}
}
}
```

**Expected behavior**
I could have handle the server, whether I choose to force close or not, when having a duplicate connection

**Raw Error**
```
Exception in thread "DefaultDispatcher-worker-6" java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.ktor.utils.io.nio.ChannelsKt.read(Channels.kt:135)
at io.ktor.network.sockets.CIOReaderKt$attachForReadingDirectImpl$1$1$1.invokeSuspend(CIOReader.kt:90)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:175)
at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:137)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:108)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:306)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:316)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:248)
at io.ktor.network.selector.SelectorManagerSupport.handleSelectedKey(SelectorManagerSupport.kt:84)
at io.ktor.network.selector.SelectorManagerSupport.handleSelectedKeys(SelectorManagerSupport.kt:64)
at io.ktor.network.selector.ActorSelectorManager.process(ActorSelectorManager.kt:73)
at io.ktor.network.selector.ActorSelectorManager$process$1.invokeSuspend(ActorSelectorManager.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.