Skip to content

Commit 0152ff2

Browse files
committed
chore: ktor tcp server test sample
1 parent b088553 commit 0152ff2

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
@file:OptIn(DelicateCoroutinesApi::class)
2+
3+
package dev.suresh
4+
5+
import io.ktor.network.selector.SelectorManager
6+
import io.ktor.network.sockets.aSocket
7+
import io.ktor.network.sockets.awaitClosed
8+
import io.ktor.network.sockets.openReadChannel
9+
import io.ktor.network.sockets.openWriteChannel
10+
import java.net.InetSocketAddress
11+
import java.time.Duration
12+
import kotlin.concurrent.thread
13+
import kotlinx.coroutines.DelicateCoroutinesApi
14+
import kotlinx.coroutines.async
15+
import kotlinx.coroutines.newSingleThreadContext
16+
import kotlinx.coroutines.runBlocking
17+
import kotlinx.coroutines.test.runTest
18+
import org.junit.jupiter.api.Assertions.assertEquals
19+
20+
class KtorTests {
21+
22+
// @Test
23+
fun tcpServer() = runTest {
24+
val address = InetSocketAddress.createUnresolved("localhost", 9999)
25+
val selectorManager = SelectorManager(newSingleThreadContext("TcpRunner"))
26+
27+
aSocket(selectorManager).tcp().bind(address.hostName, address.port).use { serverSocket ->
28+
println("TCP server is listening at ${serverSocket.localAddress}")
29+
30+
repeat(5_000) {
31+
// If the thread hangs, this won't complete within the timeout
32+
println("Awaiting new connection")
33+
val socketAsync = async { serverSocket.accept() }
34+
aSocket(selectorManager).tcp().connect(address.hostName, address.port)
35+
val socket = socketAsync.await()
36+
println("Accepted connection from ${socket.remoteAddress}, $socket")
37+
38+
println("Closing connection to ${socket.remoteAddress}")
39+
40+
val thread = thread {
41+
val readChannel = socket.openReadChannel()
42+
val writeChannel = socket.openWriteChannel(autoFlush = true)
43+
44+
socket.close()
45+
runBlocking {
46+
// With manual flushAndClose of the WriteChannel, 3.2.0 works.
47+
//
48+
// Note: This is _usually_ not needed, only a small percentage of connections
49+
// fail to close properly without it.
50+
// writeChannel.flushAndClose()
51+
socket.awaitClosed()
52+
}
53+
}
54+
55+
thread.join(Duration.ofMillis(500))
56+
assertEquals(Thread.State.TERMINATED, thread.state)
57+
}
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)