Search results

There are no results.

std.net.socket.Socket

class pub Socket

A low-level, non-blocking IPv4 or IPv6 socket.

Static methods

ipv4

Show source code
Hide source code
fn pub static ipv4(type: Type) -> Result[Socket, Error] {
  let sock = RawSocket(
    inner: 0 as Int32,
    registered: 0 as UInt8,
    unix: 0 as UInt8,
  )

  match inko_socket_new(IPV4, type.into_int, mut sock) as Int {
    case 0 -> Result.Ok(Socket(raw: sock, deadline: NO_DEADLINE))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub static ipv4(type: Type) -> Result[Socket, Error]

Creates a new IPv4 socket.

Examples

import std.net.socket (Type, Socket)

Socket.ipv4(Type.DGRAM).get

ipv6

Show source code
Hide source code
fn pub static ipv6(type: Type) -> Result[Socket, Error] {
  let sock = RawSocket(
    inner: 0 as Int32,
    registered: 0 as UInt8,
    unix: 0 as UInt8,
  )

  match inko_socket_new(IPV6, type.into_int, mut sock) as Int {
    case 0 -> Result.Ok(Socket(raw: sock, deadline: NO_DEADLINE))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub static ipv6(type: Type) -> Result[Socket, Error]

Creates a new IPv6 socket.

Examples

import std.net.socket (Type, Socket)

Socket.ipv6(Type.DGRAM).get

Instance methods

accept

Show source code
Hide source code
fn pub accept -> Result[Socket, Error] {
  let sock = RawSocket(
    inner: 0 as Int32,
    registered: 0 as UInt8,
    unix: 0 as UInt8,
  )

  match
    inko_socket_accept(_INKO.state, _INKO.process, @raw, @deadline, mut sock)
      as Int
  {
    case 0 -> Result.Ok(Socket(raw: sock, deadline: NO_DEADLINE))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub accept -> Result[Socket, Error]

Accepts a new incoming connection from this socket.

This method will not return until a connection is available.

Examples

Accepting a connection and reading data from the connection:

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let listener = Socket.ipv4(Type.STREAM).get
let stream = Socket.ipv4(Type.STREAM).get

listener.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
listener.listen.get

stream.connect(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
stream.write_string('ping').get

let client = listener.accept.get
let buffer = ByteArray.new

client.read(into: buffer, size: 4).get

buffer.to_string # => 'ping'

bind

Show source code
Hide source code
fn pub mut bind(ip: ref IpAddress, port: Int) -> Result[Nil, Error] {
  match inko_socket_bind(@raw, ip.to_string, port) {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut bind(ip: ref IpAddress, port: Int) -> Result[Nil, Error]

Binds this socket to the specified address.

Examples

Binding a socket:

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let socket = Socket.ipv4(Type.DGRAM).get

socket.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get

broadcast=

Show source code
Hide source code
fn pub mut broadcast=(value: Bool) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_BROADCAST, value.to_int)
}
fn pub mut broadcast=(value: Bool) -> Result[Nil, Error]

Sets the value of the SO_BROADCAST option.

connect

Show source code
Hide source code
fn pub mut connect(ip: ref IpAddress, port: Int) -> Result[Nil, Error] {
  match
    inko_socket_connect(
      _INKO.state,
      _INKO.process,
      @raw,
      ip.to_string,
      port,
      @deadline,
    )
  {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut connect(ip: ref IpAddress, port: Int) -> Result[Nil, Error]

Connects this socket to the specified address.

Examples

Connecting a socket:

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let listener = Socket.ipv4(Type.STREAM).get
let client = Socket.ipv4(Type.STREAM).get

socket.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
socket.listen.get
client.connect(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get

flush

Show source code
Hide source code
fn pub mut flush -> Result[Nil, Never] {
  Result.Ok(nil)
}
fn pub mut flush -> Result[Nil, Never]

Flushes any pending writes.

keepalive=

Show source code
Hide source code
fn pub mut keepalive=(value: Bool) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_KEEPALIVE, value.to_int)
}
fn pub mut keepalive=(value: Bool) -> Result[Nil, Error]

Sets the value of the SO_KEEPALIVE option.

linger

Show source code
Hide source code
fn pub linger -> Option[Duration] {
  let linger = Linger(l_onoff: 0 as Int32, l_linger: 0 as Int32)
  let size = 8 as Int32
  let res = getsockopt(
    @raw.inner,
    const.SOL_SOCKET as Int32,
    const.SO_LINGER as Int32,
    (mut linger) as Pointer[UInt8],
    mut size,
  )
    as Int

  # Similar to get_option(), this method shouldn't ever reach this point, but
  # we panic just in case we do.
  if res != 0 { panic('getsockopt(2) failed: ${Error.last_os_error}') }

  if linger.l_onoff as Int != 0 {
    Option.Some(Duration.from_secs(linger.l_linger as Int))
  } else {
    Option.None
  }
}
fn pub linger -> Option[Duration]

Returns the value of the SO_LINGER option.

linger=

Show source code
Hide source code
fn pub mut linger=(value: Option[Duration]) -> Result[Nil, Error] {
  let linger = Linger(l_onoff: 0 as Int32, l_linger: 0 as Int32)

  match value {
    case Some(d) -> {
      linger.l_onoff = 1 as Int32
      linger.l_linger = d.to_secs.to_int as Int32
    }
    case _ -> {}
  }

  let res = setsockopt(
    @raw.inner,
    const.SOL_SOCKET as Int32,
    const.SO_LINGER as Int32,
    (mut linger) as Pointer[UInt8],
    8 as Int32,
  )
    as Int

  if res == 0 { Result.Ok(nil) } else { Result.Error(Error.last_os_error) }
}
fn pub mut linger=(value: Option[Duration]) -> Result[Nil, Error]

Sets the value of the SO_LINGER option.

If a Some is given, the linger value is set to the duration in seconds. If a None is given, the linger value is instead reset.

On most platforms the linger duration has a precision of whole seconds. If a Duration is supplied that is less than one second long or contains fractional seconds, the value may be truncated or rounded to the nearest second.

listen

Show source code
Hide source code
fn pub mut listen -> Result[Nil, Error] {
  match inko_socket_listen(@raw, MAXIMUM_LISTEN_BACKLOG) {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut listen -> Result[Nil, Error]

Marks this socket as being ready to accept incoming connections using accept().

Examples

Marking a socket as a listener:

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let socket = Socket.ipv4(Type.STREAM).get

socket.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
socket.listen.get

local_address

Show source code
Hide source code
fn pub local_address -> Result[SocketAddress, Error] {
  let raw = RawAddress(address: '', port: 0)

  match inko_socket_local_address(_INKO.state, @raw, mut raw) as Int {
    case 0 -> Result.Ok(SocketAddress.new(raw.address, raw.port))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub local_address -> Result[SocketAddress, Error]

Returns the local address of this socket.

no_delay=

Show source code
Hide source code
fn pub mut no_delay=(value: Bool) -> Result[Nil, Error] {
  set_option(const.IPPROTO_TCP, const.TCP_NODELAY, value.to_int)
}
fn pub mut no_delay=(value: Bool) -> Result[Nil, Error]

Sets the value of the TCP_NODELAY option.

no_delay?

Show source code
Hide source code
fn pub no_delay? -> Bool {
  get_option(const.IPPROTO_TCP, const.TCP_NODELAY) != 0
}
fn pub no_delay? -> Bool

Returns true if the TCP_NODELAY option is set.

only_ipv6=

Show source code
Hide source code
fn pub mut only_ipv6=(value: Bool) -> Result[Nil, Error] {
  set_option(const.IPPROTO_IPV6, const.IPV6_V6ONLY, value.to_int)
}
fn pub mut only_ipv6=(value: Bool) -> Result[Nil, Error]

Sets the value of the IPV6_V6ONLY option.

peer_address

Show source code
Hide source code
fn pub peer_address -> Result[SocketAddress, Error] {
  let raw = RawAddress(address: '', port: 0)

  match inko_socket_peer_address(_INKO.state, @raw, mut raw) as Int {
    case 0 -> Result.Ok(SocketAddress.new(raw.address, raw.port))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub peer_address -> Result[SocketAddress, Error]

Returns the peer address of this socket.

print

Show source code
Hide source code
fn pub mut print(string: String) -> Result[Nil, Error] {
  write_string(string).then(fn (_) { write_string('\n') })
}
fn pub mut print(string: String) -> Result[Nil, Error]

Writes the entirety of string to the underlying stream, followed by writing a Unix newline to the stream.

read

Show source code
Hide source code
fn pub mut read(into: mut ByteArray, size: Int) -> Result[Int, Error] {
  match
    inko_socket_read(_INKO.state, _INKO.process, @raw, into, size, @deadline)
  {
    case { @tag = 0, @value = v } -> Result.Ok(v)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut read(into: mut ByteArray, size: Int) -> Result[Int, Error]

Reads bytes from a stream into a ByteArray.

The return value is the number of bytes read.

The size argument specifies how many bytes are to be read. The actual number of bytes read may be less than this value.

read_all

Show source code
Hide source code
fn pub mut read_all(bytes: mut ByteArray) -> Result[Int, Error] {
  let mut total = 0
  let mut read_size = INITIAL_READ_ALL_SIZE

  loop {
    let bytes_read = try read(into: bytes, size: read_size)

    if bytes_read == 0 { return Result.Ok(total) }

    total += bytes_read

    # To reduce the overhead of large buffer reads, we increase the buffer
    # size as more data is read.
    if read_size < MAX_READ_ALL_SIZE { read_size *= 2 }
  }
}
fn pub mut read_all(bytes: mut ByteArray) -> Result[Int, Error]

Reads all bytes from the stream into the ByteArray.

If an error is encountered while reading, this method stops reading any more bytes and re-throws the error.

The return value is the number of bytes read.

receive_buffer_size=

Show source code
Hide source code
fn pub mut receive_buffer_size=(value: Int) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_RCVBUF, value.to_int)
}
fn pub mut receive_buffer_size=(value: Int) -> Result[Nil, Error]

Sets the value of the SO_RCVBUF option.

receive_from

Show source code
Hide source code
fn pub mut receive_from(
  bytes: mut ByteArray,
  size: Int,
) -> Result[SocketAddress, Error] {
  let raw = RawAddress(address: '', port: 0)

  match
    inko_socket_receive_from(
      _INKO.state,
      _INKO.process,
      @raw,
      bytes,
      size,
      @deadline,
      mut raw,
    )
      as Int
  {
    case 0 -> Result.Ok(SocketAddress.new(raw.address, raw.port))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut receive_from(bytes: mut ByteArray, size: Int) -> Result[SocketAddress, Error]

Receives a single datagram message on the socket, returning the address the message was sent from.

The message is read into the given ByteArray, and up to size bytes will be read.

Examples

Sending a message to ourselves and receiving it:

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let socket = Socket.ipv4(Type.DGRAM).get
let bytes = ByteArray.new

socket
  .send_string_to(
    'hello',
    ip: IpAddress.v4(0, 0, 0, 0),
    port: 9999
  )
  .get

let received_from = socket.receive_from(bytes: bytes, size: 5).get

bytes.to_string       # => 'hello'
received_from.address # => '0.0.0.0'
received_from.port    # => 9999

reset_deadline

Show source code
Hide source code
fn pub mut reset_deadline {
  @deadline = NO_DEADLINE
}
fn pub mut reset_deadline

Clears the deadline to apply to socket operations.

reuse_address=

Show source code
Hide source code
fn pub mut reuse_address=(value: Bool) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_REUSEADDR, value.to_int)
}
fn pub mut reuse_address=(value: Bool) -> Result[Nil, Error]

Sets the value of the SO_REUSEADDR option.

reuse_port=

Show source code
Hide source code
fn pub mut reuse_port=(value: Bool) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_REUSEPORT, value.to_int)
}
fn pub mut reuse_port=(value: Bool) -> Result[Nil, Error]

Sets the value of the SO_REUSEPORT option.

Not all platforms may support this option, in which case the supplied argument will be ignored.

send_buffer_size=

Show source code
Hide source code
fn pub mut send_buffer_size=(value: Int) -> Result[Nil, Error] {
  set_option(const.SOL_SOCKET, const.SO_SNDBUF, value.to_int)
}
fn pub mut send_buffer_size=(value: Int) -> Result[Nil, Error]

Sets the value of the SO_SNDBUF option.

send_bytes_to

Show source code
Hide source code
fn pub mut send_bytes_to(
  bytes: ref ByteArray,
  ip: ref IpAddress,
  port: Int,
) -> Result[Int, Error] {
  match
    inko_socket_send_bytes_to(
      _INKO.state,
      _INKO.process,
      @raw,
      bytes,
      ip.to_string,
      port,
      @deadline,
    )
  {
    case { @tag = 0, @value = v } -> Result.Ok(v)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut send_bytes_to(bytes: ref ByteArray, ip: ref IpAddress, port: Int) -> Result[Int, Error]

Sends a ByteArray to the given address.

The return value is the number of bytes sent.

Examples

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let socket = Socket.ipv4(Type.DGRAM).get
let bytes = 'hello'.to_byte_array

socket.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
socket
  .send_bytes_to(
    bytes: bytes,
    ip: IpAddress.v4(0, 0, 0, 0),
    port: 9999
  )
  .get

send_string_to

Show source code
Hide source code
fn pub mut send_string_to(
  string: String,
  ip: ref IpAddress,
  port: Int,
) -> Result[Int, Error] {
  match
    inko_socket_send_string_to(
      _INKO.state,
      _INKO.process,
      @raw,
      string,
      ip.to_string,
      port,
      @deadline,
    )
  {
    case { @tag = 0, @value = v } -> Result.Ok(v)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut send_string_to(string: String, ip: ref IpAddress, port: Int) -> Result[Int, Error]

Sends a String to the given address.

The return value is the number of bytes sent.

Examples

import std.net.socket (Socket, Type)
import std.net.ip (IpAddress)

let socket = Socket.ipv4(Type.DGRAM).get

socket.bind(ip: IpAddress.v4(0, 0, 0, 0), port: 9999).get
socket
  .send_string_to(
    string: 'hello',
    ip: IpAddress.v4(0, 0, 0, 0),
    port: 9999
  )
  .get

shutdown

Show source code
Hide source code
fn pub mut shutdown -> Result[Nil, Error] {
  match inko_socket_shutdown_read_write(@raw) {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut shutdown -> Result[Nil, Error]

Shuts down both the reading and writing half of this socket.

shutdown_read

Show source code
Hide source code
fn pub mut shutdown_read -> Result[Nil, Error] {
  match inko_socket_shutdown_read(@raw) {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut shutdown_read -> Result[Nil, Error]

Shuts down the reading half of this socket.

shutdown_write

Show source code
Hide source code
fn pub mut shutdown_write -> Result[Nil, Error] {
  match inko_socket_shutdown_write(@raw) {
    case { @tag = 1, @value = _ } -> Result.Ok(nil)
    case { @tag = _, @value = e } -> Result.Error(Error.from_os_error(e))
  }
}
fn pub mut shutdown_write -> Result[Nil, Error]

Shuts down the writing half of this socket.

timeout_after=

Show source code
Hide source code
fn pub mut timeout_after=[T: ToInstant](deadline: ref T) {
  @deadline = deadline.to_instant.to_int
}
fn pub mut timeout_after=[T: ToInstant](deadline: ref T)

Sets the point in time after which socket operations must time out, known as a "deadline".

Examples

Using a Duration results in this method calculating the absolute time after which operations time out:

import std.net.socket (Socket, Type)
import std.time (Duration)

let socket = Socket.ipv4(Type.DGRAM)

socket.timeout_after = Duration.from_secs(5)

We can also use an Instant:

import std.net.socket (Socket, Type)
import std.time (Duration, Instant)

let socket = Socket.ipv4(Type.DGRAM)

socket.timeout_after = Instant.new + Duration.from_secs(5)

try_clone

Show source code
Hide source code
fn pub try_clone -> Result[Socket, Error] {
  let sock = RawSocket(
    inner: 0 as Int32,
    registered: 0 as UInt8,
    unix: 0 as UInt8,
  )

  match inko_socket_try_clone(@raw, mut sock) as Int {
    case 0 -> Result.Ok(Socket(raw: sock, deadline: NO_DEADLINE))
    case e -> Result.Error(Error.from_os_error(e))
  }
}
fn pub try_clone -> Result[Socket, Error]

Attempts to clone the socket.

Cloning a socket may fail, such as when the program has too many open file descriptors.

ttl=

Show source code
Hide source code
fn pub mut ttl=(value: Int) -> Result[Nil, Error] {
  set_option(const.IPPROTO_IP, const.IP_TTL, value)
}
fn pub mut ttl=(value: Int) -> Result[Nil, Error]

Sets the value of the IP_TTL option.

write_bytes

Show source code
Hide source code
fn pub mut write_bytes(bytes: ref ByteArray) -> Result[Nil, Error] {
  write_all_internal(bytes.to_pointer, bytes.size)
}
fn pub mut write_bytes(bytes: ref ByteArray) -> Result[Nil, Error]

Writes the entirety of bytes to the underlying stream.

Types implementing this method must guarantee that upon returning from this method, either all of the data is written and a Ok(Nil) is returned, or an Error(Error) is returned.

write_string

Show source code
Hide source code
fn pub mut write_string(string: String) -> Result[Nil, Error] {
  write_all_internal(string.to_pointer, string.size)
}
fn pub mut write_string(string: String) -> Result[Nil, Error]

Writes the entirety of string to the underlying stream.

See Write.write_bytes for more details.

Implemented traits

std.drop.

Drop

impl Drop for Socket
std.io.

Read

impl Read for Socket
std.io.

Write

impl Write for Socket