Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

Socket

An open port with unspecified protocol.

net.Socket
pub const Socket = struct

File

lib/std/Io/net.zig:1051

Code

pub const Socket = struct {
    handle: Handle,
    /// Contains the resolved ephemeral port number if requested.
    address: IpAddress,

    pub const Mode = enum {
        /// Provides sequenced, reliable, two-way, connection-based byte
        /// streams. An out-of-band data transmission mechanism may be
        /// supported.
        stream,
        /// Supports datagrams (connectionless, unreliable messages of a fixed
        /// maximum length).
        dgram,
        /// Provides  a  sequenced,  reliable,  two-way connection-based data
        /// transmission path for datagrams of fixed maximum length; a consumer
        /// is required to read an entire packet with each input system call.
        seqpacket,
        /// Provides raw network protocol access.
        raw,
        /// Provides a reliable datagram layer that does not guarantee ordering.
        rdm,
    };

    /// Underlying platform-defined type which may or may not be
    /// interchangeable with a file system file descriptor.
    pub const Handle = std.posix.fd_t;

    /// Leaves `address` in a valid state.
    pub fn close(s: *const Socket, io: Io) void {
        io.vtable.netClose(io.userdata, (&s.handle)[0..1]);
    }

    pub fn closeMany(io: Io, sockets: []const Socket) void {
        io.vtable.netClose(io.userdata, sockets);
    }

    pub const SendError = error{
        /// The socket type requires that message be sent atomically, and the
        /// size of the message to be sent made this impossible. The message
        /// was not transmitted, or was partially transmitted.
        MessageOversize,
        /// The output queue for a network interface was full. This generally indicates that the
        /// interface has stopped sending, but may be caused by transient congestion. (Normally,
        /// this does not occur in Linux. Packets are just silently dropped when a device queue
        /// overflows.)
        ///
        /// This is also caused when there is not enough kernel memory available.
        SystemResources,
        /// No route to network.
        NetworkUnreachable,
        /// Network reached but no route to host.
        HostUnreachable,
        /// The local network interface used to reach the destination is offline.
        NetworkDown,
        /// The destination address is not listening. Can still occur for
        /// connectionless messages.
        ConnectionRefused,
        /// Operating system or protocol does not support the address family.
        AddressFamilyUnsupported,
        /// Another TCP Fast Open is already in progress.
        FastOpenAlreadyInProgress,
        /// Network session was unexpectedly closed by recipient.
        ConnectionResetByPeer,
        /// Local end has been shut down on a connection-oriented socket, or
        /// the socket was never connected.
        SocketUnconnected,
        /// An attempt was made to send to a network/broadcast address as
        /// though it was a unicast address.
        AccessDenied,
    } || Io.UnexpectedError || Io.Cancelable;

    /// Transfers `data` to `dest`, connectionless, in one packet.
    pub fn send(s: *const Socket, io: Io, dest: *const IpAddress, data: []const u8) SendError!void {
        var message: OutgoingMessage = .{ .address = dest, .data_ptr = data.ptr, .data_len = data.len };
        const err, const n = io.vtable.netSend(io.userdata, s.handle, (&message)[0..1], .{});
        if (n != 1) return err.?;
        if (message.data_len != data.len) return error.MessageOversize;
    }

    pub fn sendMany(s: *const Socket, io: Io, messages: []OutgoingMessage, flags: SendFlags) SendError!void {
        const err, const n = io.vtable.netSend(io.userdata, s.handle, messages, flags);
        if (n != messages.len) return err.?;
    }

    pub const ReceiveError = Io.Operation.NetReceive.Error || Io.Cancelable;

    /// Waits for data. Connectionless.
    ///
    /// See also:
    /// * `receiveTimeout`
    pub fn receive(s: *const Socket, io: Io, buffer: []u8) ReceiveError!IncomingMessage {
        var message: IncomingMessage = .init;
        const maybe_err, const count = (try io.operate(.{ .net_receive = .{
            .socket_handle = s.handle,
            .message_buffer = (&message)[0..1],
            .data_buffer = buffer,
            .flags = .{},
        } })).net_receive;
        if (maybe_err) |err| return err;
        assert(1 == count);
        return message;
    }

    pub const ReceiveTimeoutError = ReceiveError || Io.Timeout.Error || Io.ConcurrentError;

    /// Waits for data. Connectionless.
    ///
    /// Returns `error.Timeout` if no message arrives early enough.
    ///
    /// See also:
    /// * `receive`
    /// * `receiveManyTimeout`
    pub fn receiveTimeout(
        s: *const Socket,
        io: Io,
        buffer: []u8,
        timeout: Io.Timeout,
    ) ReceiveTimeoutError!IncomingMessage {
        var message: IncomingMessage = .init;
        const maybe_err, const count = (try io.operateTimeout(.{ .net_receive = .{
            .socket_handle = s.handle,
            .message_buffer = (&message)[0..1],
            .data_buffer = buffer,
            .flags = .{},
        } }, timeout)).net_receive;
        if (maybe_err) |err| return err;
        assert(1 == count);
        return message;
    }

    /// Waits until at least one message is delivered, possibly returning more
    /// than one message. Connectionless.
    ///
    /// Returns number of messages received, or `error.Timeout` if no message
    /// arrives early enough.
    ///
    /// See also:
    /// * `receive`
    /// * `receiveTimeout`
    pub fn receiveManyTimeout(
        s: *const Socket,
        io: Io,
        /// Function assumes each element has initialized `control` field.
        /// Initializing with `IncomingMessage.init` may be helpful.
        message_buffer: []IncomingMessage,
        data_buffer: []u8,
        flags: ReceiveFlags,
        timeout: Io.Timeout,
    ) struct { ?ReceiveTimeoutError, usize } {
        const result = io.operateTimeout(.{ .net_receive = .{
            .socket_handle = s.handle,
            .message_buffer = message_buffer,
            .data_buffer = data_buffer,
            .flags = flags,
        } }, timeout) catch |err| return .{ err, 0 };
        return result.net_receive;
    }

    pub const CreatePairError = error{
        OperationUnsupported,
        AccessDenied,
        AddressFamilyUnsupported,
        ProtocolUnsupportedBySystem,
        /// The per-process limit on the number of open file descriptors has been reached.
        ProcessFdQuotaExceeded,
        /// The system-wide limit on the total number of open files has been reached.
        SystemFdQuotaExceeded,
        /// Insufficient memory is available. The socket cannot be created
        /// until sufficient resources are freed.
        SystemResources,
        ProtocolUnsupportedByAddressFamily,
        SocketModeUnsupported,
    } || Io.UnexpectedError || Io.Cancelable;

    pub const CreatePairOptions = struct {
        family: IpAddress.Family = .ip4,
        mode: Mode = .stream,
        protocol: ?Protocol = null,
    };

    /// Create a set of two sockets that are connected to each other.
    ///
    /// Also known as "socketpair".
    pub fn createPair(io: Io, options: CreatePairOptions) CreatePairError![2]Socket {
        return io.vtable.netSocketCreatePair(io.userdata, options);
    }
}