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

socket-interfaces.mddocs/

Socket Interfaces

Ktor Network provides a comprehensive hierarchy of socket interfaces that separate concerns and enable flexible socket implementations. The interfaces follow capability-based design, allowing sockets to implement only the functionality they support.

Base Socket Interface

ASocket - Foundation Interface

interface ASocket : Closeable, DisposableHandle {
    val socketContext: Job
    val isClosed: Boolean
    suspend fun awaitClosed()
}

The base interface for all async sockets, providing lifecycle management and coroutine integration.

Properties:

  • socketContext: Job - Coroutine job managing the socket's lifecycle
  • isClosed: Boolean - Current closed state of the socket

Methods:

  • suspend fun awaitClosed() - Suspends until the socket is closed
  • close() - Inherited from Closeable, closes the socket immediately
  • dispose() - Inherited from DisposableHandle, disposes resources

Capability Interfaces

Socket Address Capabilities

interface ABoundSocket {
    val localAddress: SocketAddress
}

interface AConnectedSocket {
    val remoteAddress: SocketAddress  
}

Interfaces providing address information for sockets.

ABoundSocket:

  • localAddress: SocketAddress - The local address the socket is bound to

AConnectedSocket:

  • remoteAddress: SocketAddress - The remote address the socket is connected to

I/O Capability Interfaces

interface AReadable {
    fun attachForReading(channel: ByteChannel): WriterJob
    fun openReadChannel(): ByteReadChannel
}

interface AWritable {
    fun attachForWriting(channel: ByteChannel): ReaderJob
    fun openWriteChannel(autoFlush: Boolean = false): ByteWriteChannel
}

interface ReadWriteSocket : ASocket, AReadable, AWritable

Interfaces providing I/O capabilities for sockets.

AReadable:

  • attachForReading(channel: ByteChannel): WriterJob - Attaches a channel for reading data
  • openReadChannel(): ByteReadChannel - Opens a dedicated read channel

AWritable:

  • attachForWriting(channel: ByteChannel): ReaderJob - Attaches a channel for writing data
  • openWriteChannel(autoFlush: Boolean = false): ByteWriteChannel - Opens a dedicated write channel

Connection Acceptance

interface Acceptable<out S : ASocket> {
    suspend fun accept(): S
}

Interface for sockets that can accept incoming connections.

Methods:

  • suspend fun accept(): S - Suspends until a new connection is accepted and returns the client socket

Concrete Socket Types

TCP Socket

interface Socket : ReadWriteSocket, ABoundSocket, AConnectedSocket, CoroutineScope

Represents a connected TCP socket with full bidirectional I/O capabilities.

Capabilities:

  • Read and write data streams
  • Access to both local and remote addresses
  • Coroutine-based lifecycle management

TCP Server Socket

interface ServerSocket : ASocket, ABoundSocket, Acceptable<Socket>

Represents a TCP server socket that listens for and accepts incoming connections.

Capabilities:

  • Accept incoming TCP connections
  • Access to bound local address
  • Coroutine-based lifecycle management

Usage Examples

Working with TCP Sockets

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

suspend fun handleTcpConnection() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("example.com", 80))
    
    // Socket implements all capability interfaces
    println("Connected to: ${socket.remoteAddress}")
    println("Local address: ${socket.localAddress}")
    
    // Use I/O capabilities
    val input: ByteReadChannel = socket.openReadChannel()
    val output: ByteWriteChannel = socket.openWriteChannel(autoFlush = true)
    
    // Write HTTP request
    output.writeStringUtf8("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
    
    // Read response
    val response = input.readUTF8Line()
    println("Response: $response")
    
    socket.close()
    selectorManager.close()
}

TCP Server with Connection Handling

suspend fun runTcpServer() {
    val selectorManager = SelectorManager()
    val serverSocket = aSocket(selectorManager)
        .tcp()
        .bind(InetSocketAddress("localhost", 8080))
    
    println("Server bound to: ${serverSocket.localAddress}")
    println("Server port: ${serverSocket.port}")
    
    while (!serverSocket.isClosed) {
        try {
            // Accept new connection
            val clientSocket = serverSocket.accept()
            
            // Handle each client in a separate coroutine
            launch {
                handleClient(clientSocket)
            }
        } catch (e: Exception) {
            println("Error accepting connection: ${e.message}")
            break
        }
    }
    
    serverSocket.close()
    selectorManager.close()
}

suspend fun handleClient(clientSocket: Socket) {
    try {
        println("Client connected from: ${clientSocket.remoteAddress}")
        
        val input = clientSocket.openReadChannel()
        val output = clientSocket.openWriteChannel(autoFlush = true)
        
        // Echo server implementation
        while (!clientSocket.isClosed) {
            val line = input.readUTF8Line() ?: break
            output.writeStringUtf8("Echo: $line\n")
        }
    } catch (e: Exception) {
        println("Error handling client: ${e.message}")
    } finally {
        clientSocket.close()
    }
}

Using Channel Attachment

suspend fun useChannelAttachment() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("example.com", 80))
    
    // Create a custom byte channel for processing
    val customChannel = ByteChannel()
    
    // Attach the custom channel for reading from socket
    val writerJob = socket.attachForReading(customChannel)
    
    // Process data from the custom channel
    launch {
        while (!customChannel.isClosedForRead) {
            val line = customChannel.readUTF8Line() ?: break
            println("Processed: $line")
        }
    }
    
    // Wait for some data to be read
    delay(5000)
    
    // Clean up
    writerJob.cancel()
    socket.close()
    selectorManager.close()
}

Socket State Management

suspend fun manageSocketLifecycle() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager)
        .tcp()
        .connect(InetSocketAddress("example.com", 80))
    
    // Monitor socket state
    println("Socket opened, isClosed: ${socket.isClosed}")
    
    // Setup a coroutine to monitor when socket closes
    launch {
        socket.awaitClosed()
        println("Socket has been closed")
    }
    
    // Use socket for some operations
    val output = socket.openWriteChannel()
    output.writeStringUtf8("Hello World")
    
    // Explicitly close the socket
    socket.close()
    
    // Verify closure
    println("After close(), isClosed: ${socket.isClosed}")
    
    selectorManager.close()
}

Type Definitions

Required Import Statements

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

Related Types

  • SocketAddress, InetSocketAddress - See Address Types
  • ByteReadChannel, ByteWriteChannel, ByteChannel - From kotlinx-io
  • Job, WriterJob, ReaderJob - From kotlinx-coroutines
  • SelectorManager - See Selectors
  • BoundDatagramSocket, ConnectedDatagramSocket - See Datagram Sockets

Exception Types

class SocketTimeoutException(message: String) : Exception

Common exceptions thrown by socket operations.

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