CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-network-tvosx64

Ktor network utilities - tvOS x64 target implementation of asynchronous TCP/UDP sockets and related networking functionality for the Ktor framework

Pending
Overview
Eval results
Files

io-operations.mddocs/

I/O Operations

Socket I/O operations using ByteChannel integration for reading and writing data with support for both stream-based and packet-based communication.

Capabilities

Read/Write Socket Interface

Combined interface for sockets that support both reading and writing operations.

/**
 * Represents both readable and writable socket
 */
interface ReadWriteSocket : ASocket, AReadable, AWritable

Readable Socket Operations

Interface and operations for reading data from sockets.

/**
 * Represents a readable socket
 */
interface AReadable {
    /**
     * Attach channel for reading so incoming bytes appears in the attached channel.
     * Only one channel could be attached
     * @param channel ByteChannel to attach for reading
     * @returns a job that does supply data
     */
    fun attachForReading(channel: ByteChannel): WriterJob
}

/**
 * Open a read channel, could be done only once
 * @returns ByteReadChannel for reading data from the socket
 */
fun AReadable.openReadChannel(): ByteReadChannel

Usage Example:

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

val selectorManager = SelectorManager()
val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)

// Method 1: Open read channel directly
val readChannel = socket.openReadChannel()
val line = readChannel.readUTF8Line()
println("Received: $line")

// Method 2: Attach custom channel for reading
val customChannel = ByteChannel()
val readerJob = socket.attachForReading(customChannel)

// Read from custom channel
launch {
    val data = customChannel.readUTF8Line()
    println("Custom channel received: $data")
}

// Clean up
readerJob.cancel()
socket.close()

Writable Socket Operations

Interface and operations for writing data to sockets.

/**
 * Represents a writable socket
 */
interface AWritable {
    /**
     * Attach channel for writing so bytes written to the attached channel will be transmitted.
     * Only one channel could be attached
     * @param channel ByteChannel to attach for writing
     * @returns a job that does transmit data from the channel
     */
    fun attachForWriting(channel: ByteChannel): ReaderJob
}

/**
 * Open a write channel, could be opened only once
 * @param autoFlush whether returned channel do flush for every write operation
 * @returns ByteWriteChannel for writing data to the socket
 */
fun AWritable.openWriteChannel(autoFlush: Boolean = false): ByteWriteChannel

Usage Example:

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

val selectorManager = SelectorManager()
val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)

// Method 1: Open write channel directly
val writeChannel = socket.openWriteChannel(autoFlush = true)
writeChannel.writeStringUtf8("Hello, Server!")
// autoFlush = true means data is sent immediately

// Method 2: Manual flush control
val manualWriteChannel = socket.openWriteChannel(autoFlush = false)
manualWriteChannel.writeStringUtf8("Message 1\n")
manualWriteChannel.writeStringUtf8("Message 2\n")
manualWriteChannel.flush() // Send both messages at once

// Method 3: Attach custom channel for writing
val customChannel = ByteChannel()
val writerJob = socket.attachForWriting(customChannel)

// Write to custom channel
launch {
    customChannel.writeStringUtf8("Custom channel message")
    customChannel.flush()
}

// Clean up
writerJob.cancel()
socket.close()

Connection Wrapper

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

/**
 * Represents a connected socket with its input and output
 */
class Connection(
    val socket: Socket,
    val input: ByteReadChannel,
    val output: ByteWriteChannel
)

/**
 * Opens socket input and output channels and returns connection object
 * @returns Connection object with socket and I/O channels
 */
fun Socket.connection(): Connection

Usage Examples:

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

val selectorManager = SelectorManager()

// Simple client using Connection
suspend fun simpleClient() {
    val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)
    val connection = socket.connection()
    
    // Send request
    connection.output.writeStringUtf8("GET /api/data HTTP/1.1\r\nHost: localhost\r\n\r\n")
    connection.output.flush()
    
    // Read response
    val statusLine = connection.input.readUTF8Line()
    println("Response: $statusLine")
    
    // Read remaining headers
    while (true) {
        val header = connection.input.readUTF8Line()
        if (header.isNullOrEmpty()) break
        println("Header: $header")
    }
    
    connection.socket.close()
}

// Echo server using Connection
suspend fun echoServer() {
    val serverSocket = aSocket(selectorManager).tcp().bind("localhost", 8080)
    
    while (true) {
        val clientSocket = serverSocket.accept()
        launch {
            val connection = clientSocket.connection()
            
            try {
                while (true) {
                    val line = connection.input.readUTF8Line() ?: break
                    connection.output.writeStringUtf8("Echo: $line\n")
                    connection.output.flush()
                }
            } finally {
                connection.socket.close()
            }
        }
    }
}

// Bidirectional communication
suspend fun chatClient() {
    val socket = aSocket(selectorManager).tcp().connect("chat-server.com", 8080)
    val connection = socket.connection()
    
    // Send messages
    launch {
        while (true) {
            val message = readLine() ?: break
            connection.output.writeStringUtf8("$message\n")
            connection.output.flush()
        }
    }
    
    // Receive messages
    launch {
        while (true) {
            val message = connection.input.readUTF8Line() ?: break
            println("Received: $message")
        }
    }
    
    // Keep connection alive
    connection.socket.awaitClosed()
}

Advanced I/O Patterns

Advanced patterns for handling complex I/O scenarios.

Binary Data Handling:

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

suspend fun binaryDataExample() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)
    val connection = socket.connection()
    
    // Send binary data
    connection.output.writeByte(0x01)
    connection.output.writeInt(12345)
    connection.output.writeFloat(3.14f)
    connection.output.flush()
    
    // Read binary data
    val flag = connection.input.readByte()
    val number = connection.input.readInt()
    val pi = connection.input.readFloat()
    
    println("Received: flag=$flag, number=$number, pi=$pi")
    
    connection.socket.close()
    selectorManager.close()
}

Packet-based Communication:

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

suspend fun packetBasedExample() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)
    val connection = socket.connection()
    
    // Send packet with length prefix
    val message = "Hello, World!"
    val messageBytes = message.toByteArray()
    
    connection.output.writeInt(messageBytes.size) // Length prefix
    connection.output.writeFully(messageBytes)    // Message data
    connection.output.flush()
    
    // Read packet with length prefix
    val length = connection.input.readInt()
    val buffer = ByteArray(length)
    connection.input.readFully(buffer)
    val receivedMessage = buffer.decodeToString()
    
    println("Received packet: $receivedMessage")
    
    connection.socket.close()
    selectorManager.close()
}

Streaming Large Data:

import io.ktor.network.sockets.*
import io.ktor.network.selector.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import java.io.File

suspend fun streamingExample() {
    val selectorManager = SelectorManager()
    val socket = aSocket(selectorManager).tcp().connect("localhost", 8080)
    val connection = socket.connection()
    
    // Stream file upload
    launch {
        val file = File("large-file.dat")
        val buffer = ByteArray(8192) // 8KB buffer
        
        file.inputStream().use { fileInput ->
            while (true) {
                val bytesRead = fileInput.read(buffer)
                if (bytesRead == -1) break
                
                connection.output.writeFully(buffer, 0, bytesRead)
                connection.output.flush()
            }
        }
        
        connection.output.close() // Signal end of stream
    }
    
    // Stream file download
    launch {
        val outputFile = File("downloaded-file.dat")
        val buffer = ByteArray(8192)
        
        outputFile.outputStream().use { fileOutput ->
            while (true) {
                val bytesAvailable = connection.input.readAvailable(buffer)
                if (bytesAvailable == -1) break
                
                fileOutput.write(buffer, 0, bytesAvailable)
            }
        }
    }
    
    connection.socket.awaitClosed()
    selectorManager.close()
}

Error Handling:

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

suspend fun errorHandlingExample() {
    val selectorManager = SelectorManager()
    
    try {
        val socket = aSocket(selectorManager).tcp().connect("localhost", 8080) {
            socketTimeout = 10000 // 10 second timeout
        }
        
        val connection = socket.connection()
        
        // Wrap I/O operations in try-catch
        try {
            withTimeout(5000) { // 5 second operation timeout
                connection.output.writeStringUtf8("Hello")
                connection.output.flush()
                
                val response = connection.input.readUTF8Line()
                println("Response: $response")
            }
        } catch (e: SocketTimeoutException) {
            println("Socket timeout: ${e.message}")
        } catch (e: TimeoutCancellationException) {
            println("Operation timeout: ${e.message}")
        } catch (e: Exception) {
            println("I/O error: ${e.message}")
        } finally {
            connection.socket.close()
        }
        
    } catch (e: ConnectException) {
        println("Connection failed: ${e.message}")
    } finally {
        selectorManager.close()
    }
}

Install with Tessl CLI

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

docs

index.md

io-operations.md

selector-management.md

socket-addresses.md

socket-configuration.md

socket-creation.md

tcp-operations.md

udp-operations.md

tile.json