Skip to content

jokelbaf/kcp.kt

Repository files navigation

kcp

A pure-Kotlin Multiplatform implementation of the KCP reliable-ARQ protocol. The wire format and protocol state machine are byte-for-byte identical to the original implementation, so a Kotlin endpoint interoperates with any other KCP implementation sharing the same conversation id.

KCP trades a little bandwidth for substantially lower latency than TCP-style ARQ, which makes it a good fit for real-time traffic (games, voice, remote input) running over UDP.

Supported targets

jvm, linuxX64, linuxArm64, mingwX64, macosArm64, iosArm64, iosSimulatorArm64.

Installation

The library is published with the coordinates dev.jokelbaf:kcp:1.0.0. Add it to a Kotlin Multiplatform project:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("dev.jokelbaf:kcp:1.0.0")
        }
    }
}

Quick start

KCP is driven by four operations: send to queue outgoing messages, input to feed received packets, receive to read reassembled messages, and update to advance the clock. Whenever KCP has something to transmit it calls your output callback.

import dev.jokelbaf.kcp.Kcp

// Both endpoints of a connection must use the same conversation id.
val kcp = Kcp(conv = 0x11223344u) { buffer, size ->
    // Transmit the lower-level packet over your real transport.
    // Only the first `size` bytes are valid; do not retain `buffer`.
    socket.send(buffer, size)
}

// Optional tuning. "Fast" mode: nodelay on, 10 ms tick, fast resend after 2 dup-acks,
// congestion window disabled.
kcp.noDelay(nodelay = 1, interval = 10, resend = 2, nc = 1)
kcp.setWndSize(sndWnd = 128, rcvWnd = 128)

// Queue an application message (split into fragments automatically when needed).
kcp.send("hello, world".encodeToByteArray())

// Run this loop on a timer and whenever a datagram arrives:
fun tick(nowMillis: UInt, incoming: ByteArray?) {
    incoming?.let { kcp.input(it) }      // hand received datagrams to KCP
    kcp.update(nowMillis)                // drive retransmits / acks / flushing

    while (true) {                       // drain fully received messages
        val message = kcp.receive() ?: break
        println(message.decodeToString())
    }
}

The current timestamp passed to [update] and [check] is a 32-bit millisecond clock (UInt). Derive it from any monotonic source, e.g. on the JVM:

val now: UInt = System.currentTimeMillis().toUInt()

Scheduling updates efficiently

Instead of calling update on a fixed timer, you can ask KCP when it next needs attention:

val next: UInt = kcp.check(now)   // timestamp of the next required update
// sleep until `next`, then call kcp.update(...) again

API overview

Member Description
send(data, offset, length) Queue an application message for reliable delivery.
receive() / recv(buffer, …) Read the next complete message (allocating, or into your buffer).
input(data, offset, size) Feed a received lower-level packet into KCP.
update(current) Advance the clock and flush due acks/data/probes.
check(current) Timestamp at which update should next be called.
flush() Force an immediate flush.
peekSize() Size of the next complete message, or -1.
waitSnd() Number of packets queued plus in flight.
noDelay(nodelay, interval, resend, nc) Latency/retransmit tuning.
setWndSize(sndWnd, rcvWnd) Send/receive window sizes in packets.
setMtu(mtu) Change the MTU (default 1400).
setCongestionControl(ops) Install a custom algorithm, or null for the built-in one.

Streaming mode

Set kcp.stream = true on both peers to treat the connection as an unframed byte stream (message boundaries are not preserved), instead of the default datagram mode.

Building and testing

./gradlew build        # build all targets
./gradlew jvmTest      # run the test suite on the JVM
./gradlew linuxX64Test # run the test suite on Kotlin/Native

The test suite covers codec round-trips, fragmentation, stream mode, flow control, pluggable congestion control and a lossy-network simulation reproducing the reference project's three modes.

License

MIT

About

A pure Kotlin Multiplatform implementation of the KCP reliable-ARQ protocol.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages