package eio

  1. Overview
  2. Docs

Network sockets and addresses.

Example:

let addr = `Tcp (Ipaddr.V4.loopback, 8080)

let http_get ~net ~stdout addr =
  Switch.run @@ fun sw ->
  let flow = Net.connect ~sw net addr in
  Flow.copy_string "GET / HTTP/1.0\r\n\r\n" flow;
  Flow.shutdown flow `Send;
  Flow.copy flow stdout
type connection_failure =
  1. | Refused of Exn.Backend.t
  2. | No_matching_addresses
  3. | Timeout
type error =
  1. | Connection_reset of Exn.Backend.t
    (*

    This is a wrapper for epipe, econnreset and similar errors. It indicates that the flow has failed, and data may have been lost.

    *)
  2. | Connection_failure of connection_failure
type Exn.err +=
  1. | E of error
val err : error -> exn

err e is Eio.Exn.create (Net e)

module Ipaddr : sig ... end

IP addresses.

module Sockaddr : sig ... end

Network addresses.

Types

type socket_ty = [
  1. | `Socket
  2. | `Close
]
type 'a socket = [> socket_ty ] as 'a Std.r
type 'tag stream_socket_ty = [
  1. | `Stream
  2. | `Platform of 'tag
  3. | `Shutdown
  4. | socket_ty
  5. | Flow.source_ty
  6. | Flow.sink_ty
]
type 'a stream_socket = 'a Std.r constraint 'a = [> [> `Generic ] stream_socket_ty ]
type 'tag listening_socket_ty = [
  1. | `Accept
  2. | `Platform of 'tag
  3. | socket_ty
]
type 'a listening_socket = 'a Std.r constraint 'a = [> [> `Generic ] listening_socket_ty ]
type 'a connection_handler = 'a stream_socket -> Sockaddr.stream -> unit

A _ connection_handler handles incoming connections from a listening socket.

type 'tag datagram_socket_ty = [
  1. | `Datagram
  2. | `Platform of 'tag
  3. | `Shutdown
  4. | socket_ty
]
type 'a datagram_socket = 'a Std.r constraint 'a = [> [> `Generic ] datagram_socket_ty ]
type 'tag ty = [
  1. | `Network
  2. | `Platform of 'tag
]
type 'a t = 'a Std.r constraint 'a = [> [> `Generic ] ty ]

Out-bound Connections

val connect : sw:Switch.t -> [> 'tag ty ] t -> Sockaddr.stream -> 'tag stream_socket_ty Std.r

connect ~sw t addr is a new socket connected to remote address addr.

The new socket will be closed when sw finishes, unless closed manually first.

val with_tcp_connect : ?timeout:Time.Timeout.t -> host:string -> service:string -> [> 'tag ty ] Std.r -> ('tag stream_socket_ty Std.r -> 'b) -> 'b

with_tcp_connect ~host ~service t f creates a tcp connection conn to host and service and executes f conn.

conn is closed after f returns (if it isn't already closed by then).

host is either an IP address or a domain name, eg. "www.example.org", "www.ocaml.org" or "127.0.0.1".

service is an IANA recognized service name or port number, eg. "http", "ftp", "8080" etc. See https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml.

Addresses are tried in the order they are returned by getaddrinfo, until one succeeds.

  • parameter timeout

    Limits how long to wait for each connection attempt before moving on to the next. By default there is no timeout (beyond what the underlying network does).

  • raises Connection_failure

    A connection couldn't be established for any of the addresses defined for host.

Incoming Connections

val listen : ?reuse_addr:bool -> ?reuse_port:bool -> backlog:int -> sw:Switch.t -> [> 'tag ty ] Std.r -> Sockaddr.stream -> 'tag listening_socket_ty Std.r

listen ~sw ~backlog t addr is a new listening socket bound to local address addr.

The new socket will be closed when sw finishes, unless closed manually first.

On platforms that support this, passing port 0 will bind to a random port.

For (non-abstract) Unix domain sockets, the path will be removed afterwards.

  • parameter backlog

    The number of pending connections that can be queued up (see listen(2)).

  • parameter reuse_addr

    Set the Unix.SO_REUSEADDR socket option. For Unix paths, also remove any stale left-over socket.

  • parameter reuse_port

    Set the Unix.SO_REUSEPORT socket option.

accept ~sw socket waits until a new connection is ready on socket and returns it.

The new socket will be closed automatically when sw finishes, if not closed earlier. If you want to handle multiple connections, consider using accept_fork instead.

val accept_fork : sw:Switch.t -> [> 'tag listening_socket_ty ] Std.r -> on_error:(exn -> unit) -> [< 'tag stream_socket_ty ] connection_handler -> unit

accept_fork ~sw ~on_error socket fn accepts a connection and handles it in a new fiber.

After accepting a connection to socket, it runs fn flow client_addr in a new fiber.

flow will be closed when fn returns. The new fiber is attached to sw.

  • parameter on_error

    Called if connection_handler raises an exception. This is typically a good place to log the error and continue. If the exception is an Eio.Io error then the caller's address is added to it.

    If you don't want to handle connection errors, use ~on_error:raise to cancel the caller's context.

    on_error is not called for Cancel.Cancelled exceptions, which do not need to be reported.

val listening_addr : [> 'tag listening_socket_ty ] Std.r -> Sockaddr.stream

Running Servers

val run_server : ?max_connections:int -> ?additional_domains:(_ Domain_manager.t * int) -> ?stop:'a Promise.t -> on_error:(exn -> unit) -> [> 'tag listening_socket_ty ] Std.r -> [< 'tag stream_socket_ty ] connection_handler -> 'a

run_server ~on_error sock connection_handler establishes a concurrent socket server s.

It accepts incoming client connections on socket sock and handles them with accept_fork (see that for the description of on_error and connection_handler).

Running a Parallel Server

By default s runs on a single OCaml Domain. However, if additional_domains:(domain_mgr, domains) parameter is given, then s will spawn domains additional domains and run accept loops in those too. In such cases you must ensure that connection_handler only accesses thread-safe values. Note that having more than Domain.recommended_domain_count domains in total is likely to result in bad performance.

  • parameter max_connections

    The maximum number of concurrent connections accepted by s at any time. The default is Int.max_int.

  • parameter stop

    Resolving this promise causes s to stop accepting new connections. run_server will wait for all existing connections to finish and then return. This is useful to upgrade a server without clients noticing. To stop immediately, cancelling all connections, just cancel s's fiber instead.

  • parameter on_error

    Connection error handler (see accept_fork).

  • raises Invalid_argument

    if max_connections <= 0. if additional_domains = (domain_mgr, domains) is used and domains < 0.

Datagram Sockets

val datagram_socket : ?reuse_addr:bool -> ?reuse_port:bool -> sw:Switch.t -> [> 'tag ty ] Std.r -> [< Sockaddr.datagram | `UdpV4 | `UdpV6 ] -> 'tag datagram_socket_ty Std.r

datagram_socket ~sw t addr creates a new datagram socket bound to addr. The new socket will be closed when sw finishes.

`UdpV4 and `UdpV6 represents IPv4 and IPv6 datagram client sockets where the OS assigns the next available socket address and port automatically. `Udp .. can be used to create both listening server socket and client socket.

  • parameter reuse_addr

    Set the Unix.SO_REUSEADDR socket option.

  • parameter reuse_port

    Set the Unix.SO_REUSEPORT socket option.

val send : _ datagram_socket -> ?dst:Sockaddr.datagram -> Cstruct.t list -> unit

send sock buf sends the data in buf using the the datagram socket sock.

  • parameter dst

    If sock isn't connected, this provides the destination.

recv sock buf receives data from the socket sock putting it in buf. The number of bytes received is returned along with the sender address and port. If the buf is too small then excess bytes may be discarded depending on the type of the socket the message is received from.

DNS queries

val getaddrinfo : ?service:string -> _ t -> string -> Sockaddr.t list

getaddrinfo ?service t node returns a list of IP addresses for node. node is either a domain name or an IP address.

  • parameter service

    is a human friendly textual name for internet services assigned by IANA., eg. 'http', 'https', 'ftp', etc.

    For a more thorough treatment, see getaddrinfo.

val getaddrinfo_stream : ?service:string -> _ t -> string -> Sockaddr.stream list

getaddrinfo_stream is like getaddrinfo, but filters out non-stream protocols.

val getaddrinfo_datagram : ?service:string -> _ t -> string -> Sockaddr.datagram list

getaddrinfo_datagram is like getaddrinfo, but filters out non-datagram protocols.

val getnameinfo : _ t -> Sockaddr.t -> string * string

getnameinfo t sockaddr is (hostname, service) corresponding to sockaddr. hostname is the registered domain name represented by sockaddr. service is the IANA specified textual name of the port specified in sockaddr, e.g. 'ftp', 'http', 'https', etc.

Closing

val close : [> `Close ] Std.r -> unit

Alias of Resource.close.

Provider Interface

module Pi : sig ... end