blob: 5692c35d69d0836b8ad4993246a229643015d341 [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001/*
2 * Copyright 2016-2017 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Roman Elizarov3d9fb682017-01-23 21:02:43 +030017package examples
18
Roman Elizarov9fe5f462018-02-21 19:05:52 +030019import kotlinx.coroutines.experimental.*
20import kotlinx.coroutines.experimental.nio.*
21import java.net.*
22import java.nio.*
23import java.nio.channels.*
24import kotlin.coroutines.experimental.*
Roman Elizarov3d9fb682017-01-23 21:02:43 +030025
26val PORT = 12345
27val CLIENT_READ_TIMEOUT = 5000L // 5 sec
28val CLIENT_WRITE_TIMEOUT = 1000L // 1 sec
29val BUFFER_SIZE = 1024
30
31fun main(args: Array<String>) = runBlocking {
32 val serverChannel =
33 AsynchronousServerSocketChannel
34 .open()
35 .bind(InetSocketAddress(PORT))
36 log("Listening on port $PORT")
37 // loop and accept connections forever
38 while (true) {
39 val client = serverChannel.aAccept()
40 val address = try {
41 val ia = client.remoteAddress as InetSocketAddress
42 "${ia.address.hostAddress}:${ia.port}"
43 } catch (ex: Throwable) {
44 log("Accepted client connection but failed to get its address because of $ex")
45 continue /* accept next connection */
46 }
47 log("Accepted client connection from $address")
48 // just start a new coroutine for each client connection
Roman Elizarov43e3af72017-07-21 16:01:31 +030049 launch(coroutineContext) {
Roman Elizarov3d9fb682017-01-23 21:02:43 +030050 try {
51 handleClient(client)
52 log("Client connection from $address has terminated normally")
53 } catch (ex: Throwable) {
54 log("Client connection from $address has terminated because of $ex")
55 }
56 }
57 }
58}
59
Roman Elizarov7cf452e2017-01-29 21:58:33 +030060suspend fun handleClient(client: AsynchronousSocketChannel) {
Roman Elizarov3d9fb682017-01-23 21:02:43 +030061 val buffer = ByteBuffer.allocate(BUFFER_SIZE)
62 while (true) {
63 val bytes = withTimeout(CLIENT_READ_TIMEOUT) { client.aRead(buffer) }
64 if (bytes < 0) break
65 buffer.flip()
66 withTimeout(CLIENT_WRITE_TIMEOUT) { client.aWrite(buffer) }
67 buffer.clear()
68 }
69}
70