Last active
April 22, 2020 10:24
-
-
Save latant/0940499253a1c4c9f5193f7f049671fa to your computer and use it in GitHub Desktop.
A demo of creating a Java NIO one threaded, non-blocking server coroutine API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface NioSocketServer { | |
| fun stop() | |
| suspend fun SelectableChannel.awaitSelection(ops: Int): SelectionKey | |
| } | |
| fun nioSocketServer(port: Int, acceptor: suspend NioSocketServer.(SocketChannel) -> Unit) { | |
| var isStopped = false | |
| val serverChannel = ServerSocketChannel.open().apply { | |
| configureBlocking(false) | |
| bind(InetSocketAddress(port)) | |
| } | |
| val selector = Selector.open() | |
| val dispatcher = object : CoroutineDispatcher() { | |
| override fun dispatch(context: CoroutineContext, block: Runnable) { block.run() } | |
| } | |
| val server = object : NioSocketServer { | |
| override suspend fun SelectableChannel.awaitSelection(ops: Int) = | |
| suspendCoroutine<SelectionKey> { cont -> register(selector, ops, cont) } | |
| override fun stop() { isStopped = false } | |
| } | |
| runBlocking(dispatcher) { | |
| while (!isStopped) { | |
| if (selector.selectNow() > 0) { | |
| selector.selectedKeys().onEach { | |
| it.cancel() | |
| (it.attachment() as Continuation<SelectionKey>).resume(it) | |
| }.clear() | |
| } | |
| serverChannel.accept()?.let { | |
| it.configureBlocking(false) | |
| async { server.acceptor(it) } | |
| } | |
| } | |
| } | |
| } | |
| fun main() { | |
| nioSocketServer(80) { channel -> | |
| val buffer = ByteBuffer.allocate(128) | |
| val selectionKey = channel.awaitSelection(SelectionKey.OP_READ) | |
| channel.read(buffer) | |
| buffer.flip() | |
| val byteArray = ByteArray(128) | |
| buffer.get(byteArray) | |
| println(byteArray.toString(Charsets.UTF_8)) | |
| channel.socket().close() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment