Network Programming in Kotlin: From Sockets to Coroutines

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Network Programming in Kotlin: From Theory to Practice



The modern world is a world of interconnected applications. Whether it's a chatbot, an online game, or a microservice architecture — network interaction is at the core of everything. And if earlier network programming was associated exclusively with Java or C++, today Kotlin is confidently entering the stage.



Why Kotlin? This language is not just a "modern Java". It has absorbed the best from the JVM world, adding conciseness, safety, and powerful asynchronous support through coroutines. In this article, we will explore how to write network programming in Kotlin — from classic sockets to elegant solutions with coroutines. You will learn how to create your own TCP server, send a UDP packet, and not go crazy with multithreading.



Why Kotlin is Suitable for Network Tasks?



Before diving into the code, let's understand why Kotlin is an excellent choice for network programming:



  • Full Java compatibility: you can use the entire arsenal of java.net, java.nio, and popular frameworks (Netty, Ktor).
  • Coroutines: asynchronous code looks like synchronous code. No callback hell.
  • Null safety: fewer chances of getting a NullPointerException when working with data streams.
  • Functional extensions: convenient extension functions for working with bytes and strings.


We will start with basic sockets (like in good old Java), and then move on to a more modern approach with coroutines.



Basics: TCP Server and Client in Kotlin



Let's start with the classics — TCP connections. In Kotlin, we use the same ServerSocket and Socket classes, but with cleaner syntax.



Writing a Simple TCP Echo Server



Our server will receive messages from the client and send them back (echo).



import java.io.BufferedReaderimport java.io.InputStreamReaderimport java.io.PrintWriterimport java.net.ServerSocket

fun main() { val port = 8080 val serverSocket = ServerSocket(port) println("Server started on port $port")

while (true) { // Block while waiting for a client val clientSocket = serverSocket.accept() println("Client connected: ${clientSocket.inetAddress.hostAddress}")

// Handle the client in a separate thread (for educational purposes) Thread { try { val input = BufferedReader(InputStreamReader(clientSocket.inputStream)) val output = PrintWriter(clientSocket.outputStream, true)

var message: String? while (input.readLine().also { message = it } != null) { println("Received: $message") output.println("Echo: $message") } } catch (e: Exception) { println("Error: ${e.message}") } finally { clientSocket.close() } }.start() }}


Note: we use Thread { ... }.start(). This works, but for production it's better to use a thread pool or coroutines (more on that later).



Client for the Echo Server



Now let's write a client that connects to the server and sends messages:



import java.io.BufferedReaderimport java.io.InputStreamReaderimport java.io.PrintWriterimport java.net.Socket

fun main() { val host = "localhost" val port = 8080

try { val socket = Socket(host, port) val output = PrintWriter(socket.outputStream, true) val input = BufferedReader(InputStreamReader(socket.inputStream))

// Send messages val messages = listOf("Hello, server!", "How are you?", "Goodbye!")

Blogs

Book Recommendations