blob: 3c380de3c1cfa3937a801e510c25c1b0de3b960a [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03002 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarovf16fd272017-02-07 11:26:00 +03003 */
4
Roman Elizarov3d9fb682017-01-23 21:02:43 +03005package examples
6
Roman Elizarov9fe5f462018-02-21 19:05:52 +03007import kotlinx.coroutines.experimental.*
8import kotlinx.coroutines.experimental.nio.*
9import java.net.*
10import java.nio.*
11import java.nio.channels.*
12import kotlin.coroutines.experimental.*
Roman Elizarov3d9fb682017-01-23 21:02:43 +030013
14val PORT = 12345
15val CLIENT_READ_TIMEOUT = 5000L // 5 sec
16val CLIENT_WRITE_TIMEOUT = 1000L // 1 sec
17val BUFFER_SIZE = 1024
18
19fun main(args: Array<String>) = runBlocking {
20 val serverChannel =
21 AsynchronousServerSocketChannel
22 .open()
23 .bind(InetSocketAddress(PORT))
24 log("Listening on port $PORT")
25 // loop and accept connections forever
26 while (true) {
27 val client = serverChannel.aAccept()
28 val address = try {
29 val ia = client.remoteAddress as InetSocketAddress
30 "${ia.address.hostAddress}:${ia.port}"
31 } catch (ex: Throwable) {
32 log("Accepted client connection but failed to get its address because of $ex")
33 continue /* accept next connection */
34 }
35 log("Accepted client connection from $address")
36 // just start a new coroutine for each client connection
Roman Elizarov43e3af72017-07-21 16:01:31 +030037 launch(coroutineContext) {
Roman Elizarov3d9fb682017-01-23 21:02:43 +030038 try {
39 handleClient(client)
40 log("Client connection from $address has terminated normally")
41 } catch (ex: Throwable) {
42 log("Client connection from $address has terminated because of $ex")
43 }
44 }
45 }
46}
47
Roman Elizarov7cf452e2017-01-29 21:58:33 +030048suspend fun handleClient(client: AsynchronousSocketChannel) {
Roman Elizarov3d9fb682017-01-23 21:02:43 +030049 val buffer = ByteBuffer.allocate(BUFFER_SIZE)
50 while (true) {
51 val bytes = withTimeout(CLIENT_READ_TIMEOUT) { client.aRead(buffer) }
52 if (bytes < 0) break
53 buffer.flip()
54 withTimeout(CLIENT_WRITE_TIMEOUT) { client.aWrite(buffer) }
55 buffer.clear()
56 }
57}
58