Up

Module Server

A Server.t represents a TCP server listening on a socket.

Signature

type ('address, 'listening_on) t constraint 'address = [<
| Import.Socket.Address.t
]
val sexp_of_t : ('address -> Sexplib.Sexp.t) -> ('listening_on -> Sexplib.Sexp.t) -> ('address, 'listening_on) t -> Sexplib.Sexp.t
val sexp_of_inet : inet -> Sexplib.Sexp.t
val sexp_of_unix : unix -> Sexplib.Sexp.t
val invariant : (_, _) t -> unit
val listening_on : (_, 'listening_on) t -> 'listening_on
val listening_on_address : ('address, _) t -> 'address
val close : ?close_existing_connections:bool -> (_, _) t -> unit Async_extra.Import.Deferred.t

close t starts closing the listening socket, and returns a deferred that becomes determined after Fd.close_finished fd on the socket's fd. It is guaranteed that t's client handler will never be called after close t. It is ok to call close multiple times on the same t; calls subsequent to the initial call will have no effect, but will return the same deferred as the original call.

With ~close_existing_connections:true, close closes the sockets of all existing connections. close does not (and cannot) stop the handlers handling the connections, but they will of course be unable to write to or read from the socket. The result of close becomes determined when all the socket file descriptors are closed and the socket's fd is closed.

val close_finished : (_, _) t -> unit Async_extra.Import.Deferred.t

close_finished becomes determined after Fd.close_finished fd on the socket's fd, i.e. the same deferred that close returns. close_finished differs from close in that it does not have the side effect of initiating a close.

val is_closed : (_, _) t -> bool

is_closed t returns true iff close t has been called.

type ('address, 'listening_on, 'callback) create_options = ?max_connections:int -> ?backlog:int -> ?on_handler_error:[
| `Raise
| `Ignore
| `Call of 'address -> exn -> unit
] -> ('address, 'listening_on) Where_to_listen.t -> 'callback -> ('address, 'listening_on) t Async_extra.Import.Deferred.t

Options for server creation:

backlog is the number of clients that can have a connection pending, as with Unix.Socket.listen. Additional connections may be rejected, ignored, or enqueued anyway, depending on OS, version, and configuration.

max_connections is the maximum number of clients that can be connected simultaneously. The server will not call accept unless the number of clients is less than max_connections, although of course potential clients can have a connection pending.

on_handler_error determines what happens if the handler throws an exception. The default is `Raise. If an exception is raised by on_handler_error (either explicitely via `Raise, or in the closure passed to `Call) no further connections will be accepted.

val create_sock : ('address, 'listening_on, 'address -> ([
| `Active
], 'address) Async_extra.Import.Socket.t -> unit Async_extra.Import.Deferred.t) create_options

create where_to_listen handler starts a server listening to a socket as specified by where_to_listen. It returns a server once the socket is ready to accept connections. The server calls handler address socket for each client that connects. If the deferred returned by handler is ever determined, or handler raises an exception, then socket is closed.

The server will stop accepting and close the listening socket when an error handler raises (either via `Raise or `Call f where f raises), or if close is called.

create where_to_listen handler is a convenience wrapper around create_sock that pass a reader and writer for the client socket to the callback. If the deferred returned by handler is ever determined, or handler raises an exception, then the reader and writer are closed.

buffer_age_limit passes on to the underlying writer option of the same name.

val listening_socket : ('address, _) t -> ([
| `Passive
], 'address) Async_extra.Import.Socket.t

listening_socket t accesses the listening socket, which should be used with care. An anticipated use is with Async_extra.Udp.bind_to_interface_exn. Accepting connections on the socket directly will circumvent max_connections and on_handler_error, however, and is not recommended.

val num_connections : (_, _) t -> int