Name

SPVM::IO::Socket - Sockets with Goroutines and Deadlines

Description

SPVM::IO::Socket is an abstract class that represents a network socket. It is designed to work seamlessly with SPVM::Go and provides powerful timeout management using absolute deadlines.

Usage

use IO::Socket::IP;
use Go;
use Go::Time;

# Create a simple TCP client
my $socket = IO::Socket::IP->new({
  PeerAddr => "example.com",
  PeerPort => 80,
});

# Set an absolute deadline (5 seconds from now)
my $deadline = Go::Time->now->add(Go::Duration_1l->new_from_sec(5.0));
$socket->set_deadline($deadline);

# Send a request
my $payload = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
$socket->syswrite($payload);

Details

IO::Socket is an abstract class. For concrete implementations, see "Well Known Child Classes".

Socket Constant Values

See Sys::Socket::Constant for constant values such as AF_INET, SOCK_STREAM, etc.

Goroutine and Non-blocking I/O

All I/O operations in this class (connect, accept, read, write, etc.) are non-blocking and integrated with goroutines.

If an I/O operation cannot be completed immediately, the current goroutine yields control to the Go scheduler, allowing other goroutines to run. When the socket becomes ready, the goroutine is automatically resumed.

Example:

# Running a concurrent TCP server
Go->go(method : void () {
  my $listen = IO::Socket::IP->new({
    LocalAddr => "0.0.0.0",
    LocalPort => 8080,
    Listen    => 10,
  });
  
  while (my $client = $listen->accept) {
    # Handle each connection in a new goroutine
    Go->go([$client : IO::Socket] method : void () {
      my $buf = (mutable string)new_string_len 1024;
      $client->sysread($buf);
      $client->syswrite("Hello from Goroutine!");
      $client->close;
    });
  }
});

Go->gosched;

Deadlines and Go::Context

This class provides three types of absolute deadlines for precise I/O control:

1. "Deadline" - A general deadline for all I/O operations.
2. "ReadDeadline" - A specific deadline for read operations (accept, recv, etc.).
3. "WriteDeadline" - A specific deadline for write operations (connect, send, etc.).

Example:

# Limit only read operations to 3 seconds
my $read_limit = Go::Time->now->add(Go::Duration_1l->new_from_sec(3.0));
$socket->set_read_deadline($read_limit);

eval {
  $socket->sysread($buffer);
};
if ($@ isa Go::Context::Error::DeadlineExceeded) {
  # Handle the case where no data was received within 3 seconds
}

These deadlines represent absolute points in time. This mechanism is designed to be compatible with the cancellation patterns found in Go::Context, ensuring that resources are leaked neither on the server nor on the client side during long-running or stalled connections.

Well Known Child Classes

Super Class

IO::Handle

Fields

Domain

has Domain : protected int;

A protocol family, such as AF_INET, AF_INET6, AF_UNIX.

Type

has Type : protected int;

A socket type, such as SOCK_STREAM, SOCK_DGRAM, SOCK_RAW.

Proto

has Proto : protected int;

A socket protocol, such as IPPROTO_TCP, IPPROTO_UDP.

Timeout

has Timeout : protected double;

An inactivity timeout in seconds for read, write, connect, and accept operations. This represents the maximum allowed idle time for a single I/O operation.

Listen

has Listen : protected int;

The number of listen backlog.

Sockaddr

has Sockaddr : protected Sys::Socket::Sockaddr;

A Sys::Socket::Sockaddr object used by "connect" or "bind" method.

Deadline

has Deadline : protected Go::Time;

An absolute deadline for I/O operations. If this deadline is reached, the operation is interrupted, and a Go::Context::Error::DeadlineExceeded exception is thrown.

ReadDeadline

has ReadDeadline : protected Go::Time;

An absolute deadline for read operations. This field overrides "Deadline" for read operations.

WriteDeadline

has WriteDeadline : protected Go::Time;

An absolute deadline for write operations. This field overrides "Deadline" for write operations.

Instance Methods

init

protected method init : void ($options : object[] = undef);

Options:

The following options are available adding to the options for IO::Handle#init method.

[Name][Type][Default Value]

  • Domain : Int = 0

  • Type : Int = 0

  • Proto : Int = 0

  • Timeout : Double = 0.0

  • Listen : Int = 0

  • Deadline : Go::Time = undef

  • ReadDeadline : Go::Time = undef

  • WriteDeadline : Go::Time = undef

The blocking mode of the socket is set to non-blocking mode.

Exceptions:

The Blocking option is not allowed in this class or its children.

sockdomain

method sockdomain : int ();

Returns the value of "Domain" field.

socktype

method socktype : int ();

Returns the value of "Type" field.

protocol

method protocol : int ();

Returns the value of "Proto" field.

timeout

method timeout : double ();

Returns the value of "Timeout" field.

set_timeout

method set_timeout : void ($timeout : double);

Sets "Timeout" field to $timeout. This value is used as an inactivity timeout.

deadline

method deadline : Go::Time ();

Returns the value of "Deadline" field.

set_deadline

method set_deadline : void ($deadline : Go::Time);

Sets "Deadline" field to $deadline.

read_deadline

method read_deadline : Go::Time ();

Returns the value of "ReadDeadline" field.

set_read_deadline

method set_read_deadline : void ($deadline : Go::Time);

Sets "ReadDeadline" field to $deadline.

write_deadline

method write_deadline : Go::Time ();

Returns the value of "WriteDeadline" field.

set_write_deadline

method set_write_deadline : void ($deadline : Go::Time);

Sets "WriteDeadline" field to $deadline.

set_blocking

method set_blocking : void ($blocking : int);

This method is the same as IO::Handle#set_blocking method, but if a true value is given to $blocking, an exception is thrown.

Exceptions:

Calling set_blocking method given a true value on an IO::Socket object is forbidden.

socket

protected method socket : void ();

Opens a socket using "Domain" field, "Type" field, and "Proto" field.

IO::Handle#FD field is set to the file descriptor of the socket.

This method calls Sys#socket method.

Exceptions:

Exceptions thrown by Sys#socket method could be thrown.

connect

protected method connect : void ();

Performs connect operation.

This method supports the inactivity "Timeout" and the absolute "Deadline" (or "WriteDeadline"). If a deadline is set, a monitor goroutine ensures the socket is closed at the deadline.

Exceptions:

If the absolute deadline is reached, a Go::Context::Error::DeadlineExceeded exception is thrown.

Exceptions thrown by Sys#connect method could be thrown.

Exceptions thrown by Go#gosched_io_write method could be thrown.

bind

protected method bind : void ();

Performs bind operation.

This method calls Sys#bind method given the value of IO::Handle#FD field and the value of "Sockaddr" field.

Exceptions:

Exceptions thrown by Sys#bind method could be thrown.

listen

protected method listen : void ();

Does the same thing that listen system call does given the file descriptor IO::Handle#FD field.

This method calls Sys#listen.

Exceptions:

"Listen" field must be greater than 0.

Exceptions thrown by Sys#listen method could be thrown.

accept

method accept : IO::Socket ($peer_ref : Sys::Socket::Sockaddr[] = undef);

Performs accept operation and returns a client socket object.

This method respects the inactivity "Timeout" and the absolute "Deadline" (or "ReadDeadline"). If a deadline is set, a monitor goroutine ensures the socket is closed at the deadline.

Returns a new client socket instance.

Exceptions:

If the absolute deadline is reached, a Go::Context::Error::DeadlineExceeded exception is thrown.

Exceptions thrown by Sys#accept method could be thrown.

Exceptions thrown by Go#gosched_io_read method could be thrown.

shutdown

method shutdown : void ($how : int);

Performs shutdown operation given the way $how.

This method calls Sys#shutdown method.

See Sys::Socket::Constant about constant values for $how: SHUT_RD, SHUT_WR, SHUT_RDWR.

Exceptions:

Exceptions thrown by Sys#shutdown method could be thrown.

close

method close : void ();

Closes the socket file descriptor.

Exceptions:

If this socket is not opened or already closed, an exception is thrown.

recvfrom

method recvfrom : int ($buffer : mutable string, $length : int, $flags : int, $from_ref : Sys::Socket::Sockaddr[], $offset : int = 0)

Performs recvfrom operation and returns read length.

If no data is available, it yields until the socket is ready, the inactivity timeout ("Timeout") expires, or the deadline ("Deadline" or "ReadDeadline") is reached.

Exceptions:

If the absolute deadline is reached, a Go::Context::Error::DeadlineExceeded exception is thrown.

Exceptions thrown by Sys#recvfrom method could be thrown.

Exceptions thrown by Go#gosched_io_read method could be thrown (e.g., Go::Error::IOTimeout).

sendto

method sendto : int ($buffer : string, $flags : int, $to : Sys::Socket::Sockaddr, $length : int = -1, $offset : int = 0);

Performs sendto operation and returns write length.

If the transmit buffer is full, it yields until space becomes available, the inactivity timeout ("Timeout") expires, or the deadline ("Deadline" or "WriteDeadline") is reached.

Exceptions:

If the absolute deadline is reached, a Go::Context::Error::DeadlineExceeded exception is thrown.

Exceptions thrown by Sys#sendto method could be thrown.

Exceptions thrown by Go#gosched_io_write method could be thrown (e.g., Go::Error::IOTimeout).

recv

method recv : int ($buffer : mutable string, $length : int = -1, $flags : int = 0, $offset : int = 0);

Performs recv operation by calling "recvfrom" with $from_ref set to undef.

Exceptions:

Exceptions thrown by "recvfrom" method could be thrown.

send

method send : int ($buffer : string, $flags : int = 0, $length : int = -1, $offset : int = 0);

Performs send operation by calling "sendto" with $to set to undef.

Exceptions:

Exceptions thrown by "sendto" method could be thrown.

sysread

method sysread : int ($buffer : mutable string, $length : int = -1, $offset : int = 0);

Perform sysread operation by calling "recv" with $flags set to 0.

Exceptions:

Exceptions thrown by "recv" method could be thrown.

syswrite

method syswrite : int ($buffer : string, $length : int = -1, $offset : int = 0);

Perform syswrite operation by calling "send" with $flags set to 0.

Exceptions:

Exceptions thrown by "send" method could be thrown.

sockname

method sockname : Sys::Socket::Sockaddr ();

Returns a Sys::Socket::Sockaddr for the local address.

Exceptions:

Exceptions thrown by Sys#getsockname method could be thrown.

peername

method peername : Sys::Socket::Sockaddr ();

Returns a Sys::Socket::Sockaddr for the remote address.

Exceptions:

Exceptions thrown by Sys#getpeername method could be thrown.

connected

method connected : Sys::Socket::Sockaddr ();

Checks if the socket is connected. Returns a Sys::Socket::Sockaddr if "peername" succeeds, otherwise returns undef.

atmark

method atmark : int ();

Calls Sys::Socket#sockatmark and returns the result.

Exceptions:

Exceptions thrown by Sys::Socket#sockatmark method could be thrown.

sockopt

method sockopt : int ($level : int, $option_name : int);

Gets a socket option by calling Sys#getsockopt.

Exceptions:

Exceptions thrown by Sys#getsockopt method could be thrown.

setsockopt

method setsockopt : void ($level : int, $option_name : int, $option_value : object of string|Int);

Sets a socket option by calling Sys#setsockopt.

Exceptions:

Exceptions thrown by Sys#setsockopt method could be thrown.

See Also

Porting

This class is a port of Perl's IO::Socket to SPVM.

Copyright & License

Copyright (c) 2026 Yuki Kimoto

MIT License