Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
0.2.0 Preview 1 · Frozen documentation

TcpStream

Owns one nonblocking TCP byte stream implementing structural Reader/Writer. Reads/writes may transfer a short prefix or return WouldBlock; no implicit wait, thread or loop is introduced. Mutable loans serialize operations and close; cross-thread sharing requires external synchronization. Move transfers close authority and leaves the source closed. Destruction closes once without flush; explicit Close reports errors and consumes authority even on native failure. Flush has no userspace cache to drain and never promises peer receipt/durability.

Sn is under heavy development. Reference extracted from this release’s bundled standard library. Public API examples are not an exhaustive compatibility test. Read the matching release guide for tested workflows and limitations. Read the status →

Module std.net

import std.net;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

TcpStream

pub final class TcpStream

Owns one nonblocking TCP byte stream implementing structural Reader/Writer. Reads/writes may transfer a short prefix or return WouldBlock; no implicit wait, thread or loop is introduced. Mutable loans serialize operations and close; cross-thread sharing requires external synchronization. Move transfers close authority and leaves the source closed. Destruction closes once without flush; explicit Close reports errors and consumes authority even on native failure. Flush has no userspace cache to drain and never promises peer receipt/durability.

Example

module example.tcp_socket;
from std.net import TcpStream, TcpListener, Address, Endpoint;
from std.io import WriteAll, ReadExactly;
fn Main() -> i32 {
    var Closed = TcpStream();
    let Input: byte[1] = [0xA1_byte];
    switch WriteAll(Closed, Input) {
        case .Err { Error = PatternPayload5085 } => {
            switch PatternPayload5085 {
                case .Failure { Reason = PatternPayload5086, Transferred = Count } => {
                    switch PatternPayload5086 {
                        case .Network { Reason = PatternPayload5087 } if (PatternPayload5087 is .Closed) => { if Count != 0 { return 1; } }
                        default => return 2;
                    }
                }
                default => return 2;
            }
        }
        default => return 2;
    }
    var Output: byte[1] = [0xB2_byte];
    switch Closed.Read(Output) {
        case .Err { Error = PatternPayload5088 } => {
            switch PatternPayload5088 {
                case .Failure { Reason = PatternPayload5089 } => {
                    switch PatternPayload5089 {
                        case .Network { Reason = PatternPayload5090 } if (PatternPayload5090 is .Closed) => {}
                        default => return 3;
                    }
                }
                default => return 3;
            }
        }
        default => return 3;
    }
    if Output[0] != 0xB2_byte { return 4; }
    switch ReadExactly(Closed, Output) {
        case .Err { Error = PatternPayload5091 } => {
            switch PatternPayload5091 {
                case .Failure { Reason = PatternPayload5092, Transferred = Count } => {
                    switch PatternPayload5092 {
                        case .Network { Reason = PatternPayload5093 } if (PatternPayload5093 is .Closed) => { if Count != 0 || Output[0] != 0xB2_byte { return 20; } }
                        default => return 21;
                    }
                }
                default => return 21;
            }
        }
        default => return 21;
    }
    switch Closed.Flush() {
        case .Err { Error = PatternPayload5094 } => {
            switch PatternPayload5094 {
                case .Failure { Reason = PatternPayload5095 } => {
                    switch PatternPayload5095 {
                        case .Network { Reason = PatternPayload5096 } if (PatternPayload5096 is .Closed) => {}
                        default => return 5;
                    }
                }
                default => return 5;
            }
        }
        default => return 5;
    }
    switch Closed.ShutdownWrite() {
        case .Err { Error = PatternPayload5097 } => {
            switch PatternPayload5097 {
                case .Failure { Reason = PatternPayload5098 } if (PatternPayload5098 is .Closed) => {}
                default => return 6;
            }
        }
        default => return 6;
    }
    switch Closed.ReadLocalEndpoint() {
        case .Err { Error = PatternPayload5099 } => {
            switch PatternPayload5099 {
                case .Failure { Reason = PatternPayload5100 } if (PatternPayload5100 is .Closed) => {}
                default => return 7;
            }
        }
        default => return 7;
    }
    switch Closed.ReadPeerEndpoint() {
        case .Err { Error = PatternPayload5101 } => {
            switch PatternPayload5101 {
                case .Failure { Reason = PatternPayload5102 } if (PatternPayload5102 is .Closed) => {}
                default => return 8;
            }
        }
        default => return 8;
    }
    if Closed.Close() is .Err { Error = _ } { return 9; }
    let Local = Endpoint.Create(Address.CreateIPv4(127_byte, 0_byte, 0_byte, 1_byte), 0_u16);
    var Listener = {
        // Scoped writable carriers end immediately after explicit payload transfer.
        var ListenerCreation = TcpListener.TryListen(Local, 8);
        switch ListenerCreation {
            case .Ok { Value = Value: mut TcpListener& } => break move(Value);
            case .Err => return 10;
        }
    };
    let Bound = switch Listener.ReadLocalEndpoint() { case .Ok { Value = Value } => break Value; case .Err => return 11; };
    if Bound.Port == 0 || !Bound.Address.IsLoopback { return 12; }
    var Moved = move(Listener);
    if !Listener.IsClosed || Moved.IsClosed { return 13; }
    // Keep the accepted stream in writable result storage until transfer.
    var Acceptance = Moved.TryAccept();
    switch Acceptance {
        case .Err { Error = PatternPayload5103 } => {
            switch PatternPayload5103 {
                case .Failure { Reason = PatternPayload5104 } if (PatternPayload5104 is .WouldBlock) => {}
                default => return 17;
            }
        }
        case .Ok { Value = Stream: mut TcpStream& } => {
            var Accepted = move(Stream);
            if Accepted.IsClosed { return 14; }
            var Transferred = move(Accepted);
            if !Accepted.IsClosed || Transferred.IsClosed { return 15; }
            if Transferred.Close() is .Err { Error = _ } { return 16; }
        }
    }
    if Moved.Close() is .Err { Error = _ } { return 18; }
    if !Moved.IsClosed || Moved.Close() is .Err { Error = _ } { return 19; }
    return 0;
}

TcpStream.init

pub init()

Creates a closed owner without native effects.

TcpStream.init

pub init(Source: readonly Self&) = delete;

Rejects duplicated close authority. Source: Existing owner.

TcpStream.init

pub init(Source: mut Self&&)

Transfers authority without native I/O, leaving source closed. Source: Writable source consumed by movement.

TcpStream.operator

pub fn operator =(Source: readonly Self&) -> void = delete;

Rejects copying ownership. Source: Existing owner. Return: No runtime result; this assignment is deleted and cannot be invoked.

TcpStream.operator

pub fn operator =(Source: mut Self&&) -> void = delete;

Requires explicit close before replacement. Source: Existing owner. Return: No runtime result; this assignment is deleted and cannot be invoked.

TcpStream.IsClosed

pub IsClosed: bool;

Observes closed/moved state without native calls. Return: True when no close authority remains.

TcpStream.ConnectAsync

pub static async fn ConnectAsync(mut Remote: Endpoint, Token: CancellationToken) -> Task<Result<Self, NetworkError>>

Connects a numeric peer without blocking a worker or resolving a name. Remote: Copied numeric endpoint with nonzero port. Token: Owned cancellation observation, inert by default. Return: Sole connected stream or typed error; failed/cancelled acquisition closes. Warning: May lazily start the shared reactor; local close authority remains retained across every suspension. No connection timeout is implied.

Example

module example.async_socket;
from std.net import TcpStream, TcpListener, UdpSocket, Address, Endpoint;
from std.io import ReadExactlyAsync, WriteAllAsync;
from std.task import Task, CancellationSource;
async fn Main() -> Task<i32> {
    let Local = Endpoint.Create(Address.CreateIPv4(127_byte, 0_byte, 0_byte, 1_byte), 0_u16);
    var Listener = {
        // Scoped writable carriers end immediately after explicit payload transfer.
        var ListenerCreation = TcpListener.TryListen(Local);
        switch ListenerCreation {
            case .Ok { Value = Value: mut TcpListener& } => break move(Value);
            case .Err => return 1;
        }
    };
    let Bound = switch Listener.ReadLocalEndpoint() { case .Ok { Value = Value } => break Value; case .Err => return 2; };
    var Stop = {
        var StopCreation = CancellationSource.TryCreate();
        switch StopCreation {
            case .Ok { Value = Value: mut CancellationSource& } => break move(Value);
            case .Err => return 23;
        }
    };
    var Accept = Listener.AcceptAsync(Stop.Token); // Retains listener until terminal await.
    var Client = {
        var ClientCreation = await TcpStream.ConnectAsync(Bound);
        switch ClientCreation {
            case .Ok { Value = Value: mut TcpStream& } => break move(Value);
            case .Err => { Stop.RequestCancellation(); let Cleanup = await move(Accept); return 3; }
        }
    };
    var Server = {
        var ServerCreation = await move(Accept);
        switch ServerCreation {
            case .Ok { Value = Value: mut TcpStream& } => break move(Value);
            case .Err => return 4;
        }
    };
    let Input: byte[2] = [0xA1_byte, 0xB2_byte];
    var Output: byte[2] = [0_byte, 0_byte];
    if await WriteAllAsync(Client, Input) is .Err { Error = _ } { return 5; }
    if await ReadExactlyAsync(Server, Output) is .Err { Error = _ } { return 6; }
    if Output[0] != Input[0] || Output[1] != Input[1] { return 7; }
    if await Client.FlushAsync() is .Err { Error = _ } { return 8; }
    if Client.ShutdownWrite() is .Err { Error = _ } { return 9; }
    switch await Server.ReadAsync(Output) { case .Ok { Value = Count } => { if Count != 0 { return 10; } } case .Err => return 11; }
    if Client.Close() is .Err { Error = _ } { return 12; }
    if Server.Close() is .Err { Error = _ } { return 13; }
    // Client has been closed after the original paired byte exchange.
    // This convenience call must refuse before native send/readiness work,
    // preserving peer bytes and proving zero progress on the closed owner.
    switch await Client.WriteAsync(Input) {
        case .Err { Error = ClosedError } => {
            switch ClosedError {
                case .Failure { Reason = Reason, Transferred = Count } => {
                    if Count != 0 { return 24; }
                    switch Reason {
                        case .Network { Reason = Network } if (Network is .Closed) => {}
                        default => return 24;
                    }
                }
                default => return 24;
            }
        }
        default => return 24;
    }
    if Listener.Close() is .Err { Error = _ } { return 14; }
    var Packet = {
        var PacketCreation = UdpSocket.TryBind(Local);
        switch PacketCreation {
            case .Ok { Value = Value: mut UdpSocket& } => break move(Value);
            case .Err => return 15;
        }
    };
    let Destination = switch Packet.ReadLocalEndpoint() { case .Ok { Value = Value } => break Value; case .Err => return 16; };
    switch await Packet.SendToAsync(Destination, Input) { case .Ok { Value = Count } => { if Count != 2 { return 17; } } case .Err => return 18; }
    switch await Packet.ReceiveFromAsync(Output) { case .Ok { Value = Receipt } => { if Receipt.Count != 2 || Receipt.IsTruncated || Receipt.Sender.Port != Destination.Port { return 19; } } case .Err => return 20; }
    if Output[0] != Input[0] || Output[1] != Input[1] { return 21; }
    if Packet.Close() is .Err { Error = _ } { return 22; }
    return 0;
}

TcpStream.ConnectAsync

pub static fn ConnectAsync(mut Remote: Endpoint) -> Task<Result<Self, NetworkError>>

Supplies the omitted arguments to ConnectAsync. Note: Defaults: Token = CancellationToken(). Remote: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.ConnectAsync

pub static async fn ConnectAsync(mut Remote: Endpoint, Limit: Deadline, Token: CancellationToken) -> Task<Result<Self, NetworkError>>

Connects against one unchanged absolute deadline. Limit: Finite compatible monotonic boundary or Endless; checked before attempts. Token: Owned cancellation observation, checked before deadline. Remote: Copied numeric peer with nonzero port. Return: Owned stream or typed cancellation/timeout/domain/native failure.

TcpStream.ConnectAsync

pub static fn ConnectAsync(mut Remote: Endpoint, Limit: Deadline) -> Task<Result<Self, NetworkError>>

Supplies the omitted arguments to ConnectAsync. Note: Defaults: Token = CancellationToken(). Remote: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.ReadAsync

pub async fn ReadAsync(Output: mut byte[], Token: CancellationToken) -> Task<Result<usize, IoError>>

Receives a bounded prefix, awaiting readiness only after WouldBlock. Output: Writable backing retained exclusively through terminal completion. Token: Owned cancellation observation. Return: Prefix count/EOF or typed IoError; no implicit exact-length read.

TcpStream.ReadAsync

pub fn ReadAsync(Output: mut byte[]) -> Task<Result<usize, IoError>>

Supplies the omitted arguments to ReadAsync. Note: Defaults: Token = CancellationToken(). Output: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.ReadAsync

pub async fn ReadAsync(Output: mut byte[], Limit: Deadline, Token: CancellationToken) -> Task<Result<usize, IoError>>

Performs one bounded transfer against an unchanged absolute deadline. Output: Exclusive initialized backing retained through completion. Limit: Finite compatible monotonic boundary or Endless; no retry resets it. Token: Owned cancellation observation checked before expiry. Return: Exact transfer/receipt or typed timeout/domain/cancellation/native failure.

TcpStream.ReadAsync

pub fn ReadAsync(Output: mut byte[], mut Limit: Deadline) -> Task<Result<usize, IoError>>

Supplies the omitted arguments to ReadAsync. Note: Defaults: Token = CancellationToken(). Output: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.WriteAsync

pub async fn WriteAsync(Input: readonly byte[], Token: CancellationToken) -> Task<Result<usize, IoError>>

Sends a bounded prefix without blocking a worker for readiness. Input: Readonly backing retained through terminal completion. Token: Owned cancellation observation. Return: Accepted prefix count or typed IoError; use WriteAllAsync for full transfer.

TcpStream.WriteAsync

pub fn WriteAsync(Input: readonly byte[]) -> Task<Result<usize, IoError>>

Supplies the omitted arguments to WriteAsync. Note: Defaults: Token = CancellationToken(). Input: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.WriteAsync

pub async fn WriteAsync(Input: readonly byte[], Limit: Deadline, Token: CancellationToken) -> Task<Result<usize, IoError>>

Performs one bounded transfer against an unchanged absolute deadline. Input: Readonly backing retained through completion. Limit: Finite compatible monotonic boundary or Endless; no retry resets it. Token: Owned cancellation observation checked before expiry. Return: Exact transfer/receipt or typed timeout/domain/cancellation/native failure.

TcpStream.WriteAsync

pub fn WriteAsync(Input: readonly byte[], mut Limit: Deadline) -> Task<Result<usize, IoError>>

Supplies the omitted arguments to WriteAsync. Note: Defaults: Token = CancellationToken(). Input: Same input, ownership and lifetime contract as the full operation. Limit: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.FlushAsync

pub async fn FlushAsync(Token: CancellationToken) -> Task<Result<void, IoError>>

Completes without waiting because this stream has no userspace cache. Token: Owned cancellation observation checked before completion. Return: Ok, cancelled or closed; no peer acknowledgment/durability promise.

TcpStream.FlushAsync

pub fn FlushAsync() -> Task<Result<void, IoError>>

Supplies the omitted arguments to FlushAsync. Note: Defaults: Token = CancellationToken(). Return: Exact full-operation result; no additional async frame is created.

TcpStream.FlushAsync

pub async fn FlushAsync(Limit: Deadline, Token: CancellationToken) -> Task<Result<void, IoError>>

Checks cancellation/deadline then completes this cache-free flush. Limit: Finite monotonic boundary or Endless; checked before flush. Token: Owned cancellation observation. Return: Ok or typed cancellation/timeout/domain/closed error; no peer acknowledgment.

TcpStream.FlushAsync

pub fn FlushAsync(mut Limit: Deadline) -> Task<Result<void, IoError>>

Supplies the omitted arguments to FlushAsync. Note: Defaults: Token = CancellationToken(). Limit: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.

TcpStream.Read

pub fn Read(Output: mut byte[]) -> Result<usize, IoError>

Attempts one bounded receive without waiting for readiness. Output: Exclusive initialized destination retained through return. Return: Copied prefix count or typed network IoError. Zero with positive capacity means EOF; empty destination provides no EOF evidence.

TcpStream.Write

pub fn Write(Input: readonly byte[]) -> Result<usize, IoError>

Attempts one bounded send, preserving partial acceptance. Input: Borrowed bytes retained only through return. Return: Accepted prefix count or typed network IoError; use WriteAll for complete transfer policy. No hidden retry or readiness wait occurs.

TcpStream.Flush

pub fn Flush() -> Result<void, IoError>

Completes immediately because this owner has no userspace output cache. Return: Ok for an owned socket or typed Closed error. Accepted kernel data is not guaranteed delivered, acknowledged or durable.

TcpStream.ReadLocalEndpoint

pub fn ReadLocalEndpoint() -> Result<Endpoint, NetworkError>

Copies numeric local socket endpoint without name resolution. Return: Independent endpoint or typed native/closed failure.

TcpStream.ReadPeerEndpoint

pub fn ReadPeerEndpoint() -> Result<Endpoint, NetworkError>

Copies attached numeric peer endpoint without name resolution. Return: Independent endpoint or typed native/closed failure.

TcpStream.ShutdownWrite

pub fn ShutdownWrite() -> Result<void, NetworkError>

Ends TCP sending without releasing receive/close authority. Return: Native shutdown completion or typed failure; receive remains usable.

TcpStream.Close

pub fn Close() -> Result<void, NetworkError>

Consumes close authority once; already closed is immediate success. Return: Native completion/failure with authority retired on either outcome.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library