Module Tcp.Server
A Server.t
represents a TCP server listening on a socket.
type ('address, 'listening_on) t
constraint 'address = [< Async_unix__.Unix_syscalls.Socket.Address.t ]
val sexp_of_t : ('address -> Ppx_sexp_conv_lib.Sexp.t) -> ('listening_on -> Ppx_sexp_conv_lib.Sexp.t) -> ('address, 'listening_on) t -> Ppx_sexp_conv_lib.Sexp.t
type inet
= (Async_unix__.Unix_syscalls.Socket.Address.Inet.t, int) t
val sexp_of_inet : inet -> Ppx_sexp_conv_lib.Sexp.t
type unix
= (Async_unix__.Unix_syscalls.Socket.Address.Unix.t, string) t
val sexp_of_unix : unix -> Ppx_sexp_conv_lib.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_unix__.Import.Deferred.t
close t
starts closing the listening socket, and returns a deferred that becomes determined afterFd.close_finished fd
on the socket'sfd
. It is guaranteed thatt
's client handler will never be called afterclose t
. It is ok to callclose
multiple times on the samet
; 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 ofclose
becomes determined when all the socket file descriptors are closed and the socket'sfd
is closed.
val close_finished : (_, _) t -> unit Async_unix__.Import.Deferred.t
close_finished
becomes determined afterFd.close_finished fd
on the socket'sfd
, i.e., the same deferred thatclose
returns.close_finished
differs fromclose
in that it does not have the side effect of initiating a close.
val is_closed : (_, _) t -> bool
is_closed t
returnstrue
iffclose t
has been called.
val close_finished_and_handlers_determined : (_, _) t -> unit Async_unix__.Import.Deferred.t
close_finished_and_handlers_determined t
becomes determined afterclose_finished t
is determined and the return of all active handlers is determined.
val create_sock : ?max_connections:int -> ?max_accepts_per_batch:int -> ?backlog:int -> ?socket:([ `Unconnected ], [< Async_unix__.Unix_syscalls.Socket.Address.t ] as 'address) Async_unix__.Unix_syscalls.Socket.t -> on_handler_error:[ `Call of 'address -> exn -> unit | `Ignore | `Raise ] -> ('address, 'listening_on) Where_to_listen.t -> ('address -> ([ `Active ], 'address) Async_unix__.Unix_syscalls.Socket.t -> unit Async_unix__.Import.Deferred.t) -> ('address, 'listening_on) t Async_unix__.Import.Deferred.t
create_sock where_to_listen handler
starts a server listening to a socket as specified bywhere_to_listen
. It returns a server once the socket is ready to accept connections. The server callshandler address socket
for each client that connects. If the deferred returned byhandler
is ever determined, orhandler
raises an exception, thensocket
is closed.The server will stop accepting and close the listening socket when an error handler raises (either via
`Raise
or`Call f
wheref
raises), or ifclose
is called.
val create_sock_inet : ?max_connections:int -> ?max_accepts_per_batch:int -> ?backlog:int -> ?socket:([ `Unconnected ], Async_unix__.Unix_syscalls.Socket.Address.Inet.t) Async_unix__.Unix_syscalls.Socket.t -> on_handler_error:[ `Call of Async_unix__.Unix_syscalls.Socket.Address.Inet.t -> exn -> unit | `Ignore | `Raise ] -> Where_to_listen.inet -> (Async_unix__.Unix_syscalls.Socket.Address.Inet.t -> ([ `Active ], Async_unix__.Unix_syscalls.Socket.Address.Inet.t) Async_unix__.Unix_syscalls.Socket.t -> unit Async_unix__.Import.Deferred.t) -> (Async_unix__.Unix_syscalls.Socket.Address.Inet.t, int) t
as
create_sock
, but only supports inet sockets, not unix sockets, and returns the server immediately rather than asynchronously.
val create : ?buffer_age_limit:Async_unix.Writer.buffer_age_limit -> ?max_connections:int -> ?max_accepts_per_batch:int -> ?backlog:int -> ?socket:([ `Unconnected ], [< Async_unix__.Unix_syscalls.Socket.Address.t ] as 'address) Async_unix__.Unix_syscalls.Socket.t -> on_handler_error:[ `Call of 'address -> exn -> unit | `Ignore | `Raise ] -> ('address, 'listening_on) Where_to_listen.t -> ('address -> Async_unix.Reader.t -> Async_unix.Writer.t -> unit Async_unix__.Import.Deferred.t) -> ('address, 'listening_on) t Async_unix__.Import.Deferred.t
create where_to_listen handler
is a convenience wrapper aroundcreate_sock
that pass a reader and writer for the client socket to the callback. If the deferred returned byhandler
is ever determined, orhandler
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 create_inet : ?buffer_age_limit:Async_unix.Writer.buffer_age_limit -> ?max_connections:int -> ?max_accepts_per_batch:int -> ?backlog:int -> ?socket:([ `Unconnected ], Async_unix__.Unix_syscalls.Socket.Address.Inet.t) Async_unix__.Unix_syscalls.Socket.t -> on_handler_error:[ `Call of Async_unix__.Unix_syscalls.Socket.Address.Inet.t -> exn -> unit | `Ignore | `Raise ] -> Where_to_listen.inet -> (Async_unix__.Unix_syscalls.Socket.Address.Inet.t -> Async_unix.Reader.t -> Async_unix.Writer.t -> unit Async_unix__.Import.Deferred.t) -> (Async_unix__.Unix_syscalls.Socket.Address.Inet.t, int) t
val listening_socket : ('address, _) t -> ([ `Passive ], 'address) Async_unix__.Unix_syscalls.Socket.t
listening_socket t
accesses the listening socket, which should be used with care. An anticipated use is withAsync_udp
.bind_to_interface_exn. Accepting connections on the socket directly will circumventmax_connections
andon_handler_error
, however, and is not recommended.
val num_connections : (_, _) t -> int
val set_drop_incoming_connections : (_, _) t -> bool -> unit
set_drop_incoming_connections
configures whether each incoming connection will be immediately dropped or not. This is a hack to effectively get a "pause listening" feature. We can't reliably usebacklog
andmax_num_connections
to reject incoming connections. For example, if we reachmax_num_connections
, we won't callaccept
but OS might still establish TCP connection. The client will see the connection as established but no data will be exchanged and we'd have to rely on TCP retransmit timeouts to close the connection. In many cases we would prefer to accept and then immediately close the connection. This is an intermediate solution until we do a more principled solution (but much more complicated) when we close the listening socket and then laterbind
andlisten
again when we decide to unpause the server.drop_incoming_connections
is set to false.