Socket.Tcp
A TCP connection or listener is made from an IP address and a port, and this module makes
them. Once made, it is an ordinary Socket.Connection or
Socket.Listener, used through Socket like a connection or
listener of any other kind.
Addresses are Socket.Address.Address values, IPv4 or IPv6, not text,
so a host name has to be resolved before anything connects to it. connect takes an
address; connectToHost takes text, either an address literal, used as it is,
or a host name, which it resolves with Socket.lookup first. A server
listens on an address and gets its connections from
Socket.accept or Socket.onConnection, by the rule the
Socket module describes.
What this module offers for a connection that already exists is two TCP options: Nagle's
algorithm, which holds back small writes to send them together, and keep-alive probes, which
the operating system sends on an idle connection to find out whether the peer is still there.
Both can be chosen when connecting and changed later with setNoDelay and
setKeepAlive.
Times are given in milliseconds, as Maybe Int, and the two fields of ConnectOptions that
take one read a non-positive value differently. A connect timeout of Just 0 or less is no
timeout, the same as Nothing. A keepAlive of Just 0 or less turns keep-alive on, at 1
second; only Nothing leaves it off.
Socket.Tls takes the same ConnectOptions and
ListenOptions for the TCP side of its connections and listeners.
import Socket
import Socket.Address as Address exposing (Family(..))
import Socket.Tcp
listener =
Socket.Tcp.listen (Socket.Tcp.defaultListenOptions (Address.loopback IPv4) 8080)Connecting
type alias ConnectOptions =
{ address : Address
, port_ : Int
, timeout : Maybe Int
, noDelay : Bool
, keepAlive : Maybe Int
}defaultConnectOptions : Address -> Int -> ConnectOptionsReturns options for connecting to address on port_ with no timeout, Nagle's algorithm on
(noDelay = False) and no keep-alive.
connect : ConnectOptions -> Task Error ConnectionOpens a TCP connection, succeeding once the connection is established.
Socket.Tcp.connect (Socket.Tcp.defaultConnectOptions (Address.loopback IPv4) 8080)Fails with, for example, Socket.ConnectionRefused when nothing listens
there, Socket.TimedOut when the timeout has passed, or
Socket.NetworkUnreachable when no route leads to the address.
connectToHost : String -> Int -> Task Error ConnectionOpens a TCP connection to a host given by name, or by an address literal, and a port, with the default options.
Text that Socket.Address.fromString reads as an address, such as
"127.0.0.1" or "::1", is used as it is. Anything else is resolved with
Socket.lookup, and a failed lookup fails the task with its error. The
addresses found are tried one after the other, in the order lookup returns them, until one
connects. If every attempt fails, the task fails with the last attempt's error; a name without
addresses fails with Socket.HostNotFound.
Socket.Tcp.connectToHost "localhost" 8080The default options have no timeout, so each attempt waits as long as the operating system does
before the next address is tried. For a time limit on each attempt, resolve the name with
Socket.lookup and call connect with a timeout.
Listening
type alias ListenOptions =
{ address : Address, port_ : Int, backlog : Int, ipv6Only : Bool }Where a TCP listener listens, which connections it accepts, and how it queues the ones it has not handed out yet.
port_0 lets the operating system pick a free port, whichSocket.listenerEndpointthen reports. The unspecified address (Socket.Address.any) listens on every interface.backlogis the length of the operating system's queue of connections waiting to be accepted, clamped to between 1 and 65535 (the operating system may limit it further). On the JavaScript backend it is also how many connections the listener holds for a lateraccept, as theSocketmodule describes.ipv6Onlymatters only for an IPv6 address. WhenFalse, a listener onany IPv6also accepts IPv4 connections, whose addresses are then IPv4-mapped (seeSocket.Address.unmapIPv4). WhenTrue, it accepts IPv6 connections only.
On the native backend the listening socket is made with SO_REUSEADDR, so the port can be
listened on again as soon as an earlier listener on it has closed.
defaultListenOptions : Address -> Int -> ListenOptionsReturns options for listening on address and port_ with a backlog of 511 and
ipv6Only = False.
listen : ListenOptions -> Task Error ListenerStarts listening for TCP connections, succeeding with the listener once it is bound and
listening. Fails with, for example, Socket.AddressInUse when the address
and port are taken, Socket.PermissionDenied for a privileged port, or
Socket.AddressNotAvailable for an address that does not belong to this
machine.
Connection options
setNoDelay : Bool -> Connection -> Task Error ()Turns Nagle's algorithm off for the connection (True, so small writes are sent at once) or
on (False). On a Unix domain connection, or one that has already been closed, this succeeds
and does nothing.
setKeepAlive : Maybe Int -> Connection -> Task Error ()Starts sending keep-alive probes once the connection has been idle for the given number of
milliseconds, within any limit the operating system sets (32767 seconds on Linux), or stops
sending them (Nothing). The time is rounded up to whole seconds, at least 1 second, so
Just 0 or a negative value turns probes on at 1 second rather than off.
On a Unix domain connection, or one that has already been closed, this succeeds and does nothing.
One attempt to open a TCP connection: where to connect, how long to wait, and the TCP options the connection starts with.
timeout, up to 2147483647 (about 24.8 days), is the most time, in milliseconds, to wait until the connection is established (and, forSocket.Tls.connect, until the TLS handshake is done as well); the attempt then fails withSocket.TimedOut.Nothing, orJust nwithn <= 0, waits as long as the operating system does.noDelay = Trueturns Nagle's algorithm off (TCP_NODELAY), so small writes are sent at once.keepAliveis how long, in milliseconds, the connection must be idle before keep-alive probes are sent, within any limit the operating system sets (32767 seconds on Linux). It is rounded up to whole seconds, at least 1 second, soJust 0or a negative value sends probes after 1 second.Nothingsends none.Setting
noDelayandkeepAlivehere is best effort: if the operating system refuses one, the connection is still made.