LastExceed
02/12/2020, 11:45 PMimport io.ktor.network.selector.ActorSelectorManager
import io.ktor.network.sockets.*
import kotlinx.coroutines.*
import <http://kotlinx.coroutines.io|kotlinx.coroutines.io>.*
import <http://java.net|java.net>.InetSocketAddress
import java.nio.channels.ClosedChannelException
suspend fun main() {
val echoServer = EchoServer()
supervisorScope {
launch {
echoServer.start()
}
while (readLine() != "exit") {
println("unknown command")
}
println("stopping server")
echoServer.stop()
}
}
class EchoServer {
private val listener: ServerSocket =
aSocket(ActorSelectorManager(<http://Dispatchers.IO|Dispatchers.IO>)).tcp().bind(InetSocketAddress(12345))
private val clients = mutableListOf<Socket>()
suspend fun start() {
coroutineScope {
while (true) {
val client =
try {
listener.accept()
} catch (_: ClosedChannelException) {
break
}
launch {
handleClient(client)
}
}
}
}
private suspend fun handleClient(client: Socket) {
println("new client connected")
clients.add(client)
val reader = client.openReadChannel()
val writer = client.openWriteChannel(true)
while (true) {
val message = reader.readUTF8Line() ?: run {
println("client disconnected")
return
}
writer.writeStringUtf8("$message\n")
}
}
fun stop() {
listener.close()
clients.forEach {
it.close()
}
clients.clear()
}
}
octylFractal
02/12/2020, 11:48 PMsuspend fun main()
uses an event loop and is single-threaded iirc. Therefore, since the code after launch
doesn't suspend, the server can never start.LastExceed
02/12/2020, 11:48 PMoctylFractal
02/12/2020, 11:48 PMreadLine()
though, maybe it suspends and I just can't see itoctylFractal
02/12/2020, 11:49 PMsuspend fun main()
thenoctylFractal
02/12/2020, 11:50 PM<http://Dispatchers.IO|Dispatchers.IO>
octylFractal
02/12/2020, 11:51 PMsupervisorScope
in withContext(<http://Dispatchers.IO|Dispatchers.IO>)
octylFractal
02/12/2020, 11:52 PMsuspend fun main()
is a language level feature, so it specifies no dispatcher, meaning it uses Dispatchers.Default
gildor
02/13/2020, 12:41 AMoctylFractal
02/13/2020, 12:46 AMoctylFractal
02/13/2020, 12:49 AMoctylFractal
02/13/2020, 12:50 AMimport kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
suspend fun main() {
println("[M] I'm on ${Thread.currentThread().name}")
coroutineScope {
println("[CS] I'm on ${Thread.currentThread().name}")
launch {
println("[L] I'm on ${Thread.currentThread().name}")
}
}
println("[M2] I'm on ${Thread.currentThread().name}")
}
->
[M] I'm on main
[CS] I'm on main
[L] I'm on DefaultDispatcher-worker-2
[M2] I'm on DefaultDispatcher-worker-2