Skip to content

Instantly share code, notes, and snippets.

Last active September 7, 2020 06:01
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ErikHellman/7f2b28a68fd01c6c079725083e8fc202 to your computer and use it in GitHub Desktop.
A very simple example of an echo-server using the non-blocking Java I/O APIs
package se.hellsoft.nonblocking.echo
import java.nio.ByteBuffer
import java.nio.channels.SelectionKey
import java.nio.channels.Selector
import java.nio.channels.ServerSocketChannel
import java.nio.channels.SocketChannel
* A simple non-blocking echo server.
* To test this, start the application and use something like netcat to connect to the port (9191)
fun main() {
val selector =
val buffer = ByteBuffer.allocate(1024)
val serverChannel =
serverChannel.register(selector, SelectionKey.OP_ACCEPT)
while (true) {
val count =
println("Selected $count channels!")
val selectedKeys = selector.selectedKeys()
selectedKeys.forEach {
if (!it.isValid) {
println("Invalid key - cancel it!")
try {
when {
it.isAcceptable -> { // New connection on our ServerSocketChannel
val sc = as ServerSocketChannel
val newClient = sc.accept()
if (newClient != null) {
println("New client!")
newClient.register(selector, SelectionKey.OP_READ)
it.isReadable && it.isReadInteresting -> { // Incoming data on a SocketChannel
val socket = as SocketChannel
if (socket.isConnected) {
val content = ByteArray(buffer.limit())
val text = String(content, Charsets.UTF_8)
if (text.isNotEmpty()) {
println("Received: $text")
socket.register(selector, SelectionKey.OP_WRITE, content)
it.isWritable && it.isWriteInteresting -> { // SocketChannel ready for writing
val socket = as SocketChannel
if (socket.isConnected) {
val content = it.attachment() as ByteArray
println("Wrote ${String(content, Charsets.UTF_8)} on channel")
socket.register(selector, SelectionKey.OP_READ, null)
} catch (e: Exception) {
println("Closing channel!")
val SelectionKey.isReadInteresting
get() = this.interestOps() and SelectionKey.OP_READ == SelectionKey.OP_READ
val SelectionKey.isWriteInteresting
get() = this.interestOps() and SelectionKey.OP_WRITE == SelectionKey.OP_WRITE
Copy link

How is this non-blocking?

selector.selectNow() -> is non blocking: it will almost never have anything.

while (true) {
    val count = -> is blocking, so it will wait until at least one selector is selected, while(true) is redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment