CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-network-macosarm64

Ktor network utilities for macOS ARM64 target - provides asynchronous networking components including sockets, selectors, and connection utilities for building Kotlin multiplatform network applications

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

Ktor Network provides a comprehensive set of utility functions, extensions, and helper classes that simplify common socket operations and provide convenient abstractions for networking tasks.

Socket Extension Functions

Lifecycle Extensions

val ASocket.isClosed: Boolean

suspend fun ASocket.awaitClosed()

Extensions for monitoring socket lifecycle state.

Properties:

  • isClosed: Boolean - Returns true if the socket has been closed

Methods:

  • suspend fun awaitClosed() - Suspends the current coroutine until the socket is closed

I/O Channel Extensions

fun AReadable.openReadChannel(): ByteReadChannel

fun AWritable.openWriteChannel(autoFlush: Boolean = false): ByteWriteChannel

Extensions for opening I/O channels on readable and writable sockets.

AReadable Extensions:

  • openReadChannel(): ByteReadChannel - Opens a dedicated read channel for receiving data

AWritable Extensions:

  • openWriteChannel(autoFlush: Boolean = false): ByteWriteChannel - Opens a dedicated write channel for sending data
    • autoFlush: Boolean - Whether to automatically flush written data (default: false)

Connection Utility

fun Socket.connection(): Connection

Creates a convenient Connection wrapper for TCP sockets.

Returns: Connection - A wrapper containing both input and output channels

Server Socket Extensions

val ServerSocket.port: Int

Extension property to get the port number from a server socket.

Returns: Int - The port number the server socket is bound to

Connection Wrapper Class

Connection Class

class Connection(
    val socket: Socket,
    val input: ByteReadChannel,
    val output: ByteWriteChannel
) : Closeable {
    override fun close()
}

Convenience class that combines a socket with its I/O channels for easier handling.

Properties:

  • socket: Socket - The underlying TCP socket
  • input: ByteReadChannel - Read channel for receiving data
  • output: ByteWriteChannel - Write channel for sending data

Methods:

  • close() - Closes the connection and all associated resources

Type of Service (QoS)

TypeOfService Value Class

@JvmInline
value class TypeOfService(val value: UByte) {
    constructor(value: Int) : this(value.toUByte())
    
    val intValue: Int get() = value.toInt()
    
    companion object {
        val UNDEFINED: TypeOfService
        val IPTOS_LOWCOST: TypeOfService
        val IPTOS_RELIABILITY: TypeOfService
        val IPTOS_THROUGHPUT: TypeOfService
        val IPTOS_LOWDELAY: TypeOfService
    }
}

Inline value class for IP Type of Service (ToS) field configuration.

Properties:

  • value: UByte - The underlying byte value for the ToS field
  • intValue: Int - Computed property returning the ToS value as an integer

Constructors:

  • TypeOfService(value: UByte) - Primary constructor taking a UByte value
  • TypeOfService(value: Int) - Secondary constructor taking Int and converting to UByte

Companion Constants:

  • UNDEFINED - Default/undefined ToS value
  • IPTOS_LOWCOST - Optimize for low cost
  • IPTOS_RELIABILITY - Optimize for reliability
  • IPTOS_THROUGHPUT - Optimize for high throughput
  • IPTOS_LOWDELAY - Optimize for low latency

Usage Examples

Basic Socket Lifecycle Management

import io.ktor.network.sockets.*
import io.ktor.network.selector.*

suspend fun monitorSocketLifecycle() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("example.com", 80))
    
    println("Socket connected: ${!socket.isClosed}")
    
    // Set up monitoring coroutine
    launch {
        socket.awaitClosed()
        println("Socket has been closed")
    }
    
    // Use socket...
    delay(1000)
    
    // Close and verify
    socket.close()
    println("After close: isClosed = ${socket.isClosed}")
    
    selectorManager.close()
}

Using Connection Wrapper

suspend fun useConnectionWrapper() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("httpbin.org", 80))
    
    // Create connection wrapper
    val connection = socket.connection()
    
    println("Connection established:")
    println("Socket: ${connection.socket.remoteAddress}")
    
    // Send HTTP request
    connection.output.writeStringUtf8("GET /get HTTP/1.1\r\n")
    connection.output.writeStringUtf8("Host: httpbin.org\r\n")
    connection.output.writeStringUtf8("Connection: close\r\n\r\n")
    connection.output.flush()
    
    // Read response
    val response = connection.input.readUTF8Line()
    println("Response: $response")
    
    // Connection.close() handles all cleanup
    connection.close()
    selectorManager.close()
}

Server Socket Port Utilities

suspend fun serverPortUtilities() {
    val selectorManager = SelectorManager()
    
    // Server with dynamic port assignment
    val server = aSocket(selectorManager)
        .tcp()
        .bind(InetSocketAddress("localhost", 0)) // Port 0 = any available
    
    // Get the assigned port
    val assignedPort = server.port
    println("Server listening on port: $assignedPort")
    println("Full address: ${server.localAddress}")
    
    // Another way to get port from address
    val addressPort = (server.localAddress as InetSocketAddress).port
    println("Port from address: $addressPort")
    
    server.close()
    selectorManager.close()
}

Advanced I/O Channel Usage

import io.ktor.utils.io.*

suspend fun advancedChannelUsage() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("example.com", 80))
    
    // Open channels with specific settings
    val input = socket.openReadChannel()
    val output = socket.openWriteChannel(autoFlush = true) // Auto-flush enabled
    
    // Send data
    output.writeStringUtf8("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
    
    // Read response headers
    val headers = mutableListOf<String>()
    while (true) {
        val line = input.readUTF8Line() ?: break
        if (line.isEmpty()) break // End of headers
        headers.add(line)
    }
    
    println("Response headers:")
    headers.forEach { println(it) }
    
    socket.close()
    selectorManager.close()
}

Type of Service Configuration

// Note: ToS configuration would typically be applied during socket creation
// This example shows the ToS value usage pattern

fun demonstrateTypeOfService() {
    // Different QoS requirements
    val lowLatencyToS = TypeOfService.IPTOS_LOWDELAY
    val highThroughputToS = TypeOfService.IPTOS_THROUGHPUT  
    val reliableToS = TypeOfService.IPTOS_RELIABILITY
    val lowCostToS = TypeOfService.IPTOS_LOWCOST
    
    println("ToS values:")
    println("Low Latency: ${lowLatencyToS.intValue}")
    println("High Throughput: ${highThroughputToS.intValue}")
    println("Reliability: ${reliableToS.intValue}")
    println("Low Cost: ${lowCostToS.intValue}")
    
    // Custom ToS value
    val customToS = TypeOfService(0x18) // Custom value
    println("Custom ToS: ${customToS.intValue}")
}

Error-Resilient Connection Management

suspend fun resilientConnectionManagement() {
    val selectorManager = SelectorManager()
    
    try {
        val socket = aSocket(selectorManager)
            .tcp()
            .configure {
                socketTimeout = 10000 // 10 second timeout
            }
            .connect(InetSocketAddress("example.com", 80))
        
        // Monitor connection state
        if (!socket.isClosed) {
            val connection = socket.connection()
            
            try {
                // Perform operations
                connection.output.writeStringUtf8("Hello\n")
                connection.output.flush()
                
                // Check if still connected before reading
                if (!connection.socket.isClosed) {
                    val response = connection.input.readUTF8Line()
                    println("Received: $response")
                }
                
            } catch (e: Exception) {
                println("Connection error: ${e.message}")
            } finally {
                connection.close()
            }
        }
        
    } catch (e: Exception) {
        println("Socket creation failed: ${e.message}")
    } finally {
        selectorManager.close()
    }
}

Bulk Connection Operations

suspend fun bulkConnectionOperations() {
    val selectorManager = SelectorManager()
    val connections = mutableListOf<Connection>()
    
    try {
        // Create multiple connections
        val addresses = listOf(
            InetSocketAddress("httpbin.org", 80),
            InetSocketAddress("example.com", 80),
            InetSocketAddress("google.com", 80)
        )
        
        addresses.forEach { address ->
            try {
                val socket = aSocket(selectorManager)
                    .tcp()
                    .connect(address)
                
                val connection = socket.connection()
                connections.add(connection)
                
                println("Connected to ${address}")
            } catch (e: Exception) {
                println("Failed to connect to ${address}: ${e.message}")
            }
        }
        
        // Perform operations on all connections
        connections.forEach { connection ->
            launch {
                try {
                    connection.output.writeStringUtf8("GET / HTTP/1.1\r\nHost: ${(connection.socket.remoteAddress as InetSocketAddress).hostname}\r\n\r\n")
                    connection.output.flush()
                    
                    val response = connection.input.readUTF8Line()
                    println("Response from ${connection.socket.remoteAddress}: $response")
                } catch (e: Exception) {
                    println("Operation failed for ${connection.socket.remoteAddress}: ${e.message}")
                }
            }
        }
        
        // Wait for operations to complete
        delay(5000)
        
    } finally {
        // Clean up all connections
        connections.forEach { connection ->
            try {
                connection.close()
            } catch (e: Exception) {
                println("Error closing connection: ${e.message}")
            }
        }
        selectorManager.close()
    }
}

Connection Pooling Utility

class ConnectionPool(private val selectorManager: SelectorManager) {
    private val connections = mutableMapOf<SocketAddress, MutableList<Connection>>()
    
    suspend fun getConnection(address: SocketAddress): Connection {
        val pool = connections.getOrPut(address) { mutableListOf() }
        
        return if (pool.isNotEmpty()) {
            val connection = pool.removeAt(0)
            if (!connection.socket.isClosed) {
                connection
            } else {
                createNewConnection(address)
            }
        } else {
            createNewConnection(address)
        }
    }
    
    private suspend fun createNewConnection(address: SocketAddress): Connection {
        val socket = aSocket(selectorManager)
            .tcp()
            .connect(address)
        
        return socket.connection()
    }
    
    fun returnConnection(connection: Connection) {
        if (!connection.socket.isClosed) {
            val address = connection.socket.remoteAddress
            val pool = connections.getOrPut(address) { mutableListOf() }
            pool.add(connection)
        } else {
            connection.close()
        }
    }
    
    fun closeAll() {
        connections.values.flatten().forEach { connection ->
            try {
                connection.close()
            } catch (e: Exception) {
                println("Error closing pooled connection: ${e.message}")
            }
        }
        connections.clear()
    }
}

suspend fun useConnectionPool() {
    val selectorManager = SelectorManager()
    val pool = ConnectionPool(selectorManager)
    
    try {
        val address = InetSocketAddress("httpbin.org", 80)
        
        // Get connection from pool
        val connection1 = pool.getConnection(address)
        println("Got connection: ${connection1.socket.remoteAddress}")
        
        // Use connection...
        connection1.output.writeStringUtf8("GET /get HTTP/1.1\r\nHost: httpbin.org\r\n\r\n")
        
        // Return to pool for reuse
        pool.returnConnection(connection1)
        
        // Get another connection (might be the same one)
        val connection2 = pool.getConnection(address)
        println("Got connection: ${connection2.socket.remoteAddress}")
        
        pool.returnConnection(connection2)
        
    } finally {
        pool.closeAll()
        selectorManager.close()
    }
}

Constants and Limits

Maximum Values

const val MAX_DATAGRAM_SIZE = 65535

Maximum size for UDP datagrams (65535 bytes).

Type Definitions

Required Import Statements

import io.ktor.network.sockets.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*

Related Types

  • Extends all socket interfaces - See Socket Interfaces
  • Used with socket builders - See Socket Builders
  • Enhances datagram operations - See Datagram Sockets
  • Works with all address types - See Address Types
  • ByteReadChannel, ByteWriteChannel - From kotlinx-io
  • Closeable - From Kotlin standard library

Exception Types

Utility functions may throw the same exceptions as their underlying socket operations. Always handle exceptions appropriately in production code.

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-network-macosarm64

docs

address-types.md

datagram-sockets.md

index.md

selectors.md

socket-builders.md

socket-interfaces.md

socket-options.md

utilities.md

tile.json