focal (3) socket.3erl.gz

Provided by: erlang-manpages_22.2.7+dfsg-1ubuntu0.2_all bug

NAME

       socket - Socket interface.

DESCRIPTION

       This  module  provides an API for network socket. Functions are provided to create, delete and manupilate
       the sockets aswell as sending and reciving data on them.

       The intent is that it shall be as "close as  possible"  to  the  OS  level  socket  interface.  The  only
       significant addition is that some of the functions, e.g. recv/3, has a timeout argument.

   Note:
       Some  functions  allow  for  an  asynchronous   call. This is achieved by setting the Timeout argument to
       nowait. For instance, if calling the recv/3 function with Timeout set to nowait (recv(Sock,  0,  nowait))
       when  there  is  actually nothing to read, it will return with {select,  SelectInfo} (SelectInfo contains
       the SelectRef). When data eventually arrives a 'select' message will be sent to the caller:

         : {'$socket', socket(), select, SelectRef}

       The caller can now make another call to the recv function and now expect data.

       Note that all other users are locked out until the 'current user' has called the function (recv  in  this
       case).

       Another message the user must be prepared for (when making asynchronous calls) is the abort message:

         : {'$socket', socket(), abort, Info}

       This  message  indicates that the (asynchronous) operation has been aborted. If, for instance, the socket
       has been closed (by another process), Info will be {SelectRef, closed}.

   Note:
       There is currently no support for Windows.

       Support for IPv6 has been implemented but not tested.

       SCTP has only been partly implemented (and not tested).

DATA TYPES

       domain() = local | inet | inet6

       type() = stream | dgram | raw | rdm | seqpacket

       protocol() =
           ip | tcp | udp | sctp | icmp | igmp | {raw, integer()}

       socket()

              As returned by open/2,3,4 and accept/1,2.

       select_tag()

              A tag that describes the (select) operation.

       select_ref()

              A reference that uniquely identifies the (select) operation.

       select_info() = {select_info, select_tag(), select_ref()}

       socket_counters() = [{socket_counter(), integer() >= 0}]

       socket_counter() =
           read_byte | read_fails | read_pkg | read_tries | read_waits |
           write_byte | write_fails | write_pkg | write_tries |
           write_waits

       socket_info() =
           #{counters := socket_counters(),
             num_readers := integer() >= 0,
             num_writers := integer() >= 0,
             num_acceptors := integer() >= 0}

       ip4_address() = {0..255, 0..255, 0..255, 0..255}

       ip6_address() =
           {0..65535,
            0..65535,
            0..65535,
            0..65535,
            0..65535,
            0..65535,
            0..65535,
            0..65535}

       ip_address() = ip4_address() | ip6_address()

       sockaddr() =
           sockaddr_in4() |
           sockaddr_in6() |
           sockaddr_un() |
           sockaddr_ll()

       sockaddr_in4() =
           #{family := inet,
             port := port_number(),
             addr := any | broadcast | loopback | ip4_address()}

       sockaddr_in6() =
           #{family := inet6,
             port := port_number(),
             addr := any | loopback | ip6_address(),
             flowinfo := in6_flow_info(),
             scope_id := in6_scope_id()}

       sockaddr_un() = #{family := local, path := binary() | string()}

       sockaddr_ll() =
           #{family := packet,
             protocol := integer() >= 0,
             ifindex := integer(),
             pkttype := packet_type(),
             hatype := integer() >= 0,
             addr := binary()}

       packet_type() =
           host | broadcast | multicast | otherhost | outgoing |
           loopback | user | kernel | fastroute |
           integer() >= 0

       port_number() = 0..65535

       in6_flow_info() = uint20()

       in6_scope_id() = uint32()

       send_flags() = [send_flag()]

       send_flag() = confirm | dontroute | eor | more | nosignal | oob

       recv_flags() = [recv_flag()]

       recv_flag() = cmsg_cloexec | errqueue | oob | peek | trunc

       shutdown_how() = read | write | read_write

       sockopt_level() =
           otp | socket | ip | ipv6 | tcp | udp | sctp |
           integer() >= 0

       otp_socket_option() =
           debug | iow | controlling_process | rcvbuf | rcvctrlbuf |
           sndctrlbuf | fd

       socket_option() =
           acceptconn | acceptfilter | bindtodevice | broadcast |
           busy_poll | debug | domain | dontroute | error | keepalive |
           linger | mark | oobinline | passcred | peek_off | peercred |
           priority | protocol | rcvbuf | rcvbufforce | rcvlowat |
           rcvtimeo | reuseaddr | reuseport | rxq_ovfl | setfib |
           sndbuf | sndbufforce | sndlowat | sndtimeo | timestamp | type

       ip_socket_option() =
           add_membership | add_source_membership | block_source |
           dontfrag | drop_membership | drop_source_membership |
           freebind | hdrincl | minttl | msfilter | mtu | mtu_discover |
           multicast_all | multicast_if | multicast_loop |
           multicast_ttl | nodefrag | options | pktinfo | recverr |
           recvif | recvdstaddr | recvopts | recvorigdstaddr | recvtos |
           recvttl | retopts | router_alert | sndsrcaddr | tos |
           transparent | ttl | unblock_source

       ipv6_socket_option() =
           addrform | add_membership | authhdr | auth_level | checksum |
           drop_membership | dstopts | esp_trans_level |
           esp_network_level | faith | flowinfo | hopopts |
           ipcomp_level | join_group | leave_group | mtu | mtu_discover |
           multicast_hops | multicast_if | multicast_loop | portrange |
           pktoptions | recverr | recvhoplimit | hoplimit | recvpktinfo |
           pktinfo | recvtclass | router_alert | rthdr | tclass |
           unicast_hops | use_min_mtu | v6only

       tcp_socket_option() =
           congestion | cork | info | keepcnt | keepidle | keepintvl |
           maxseg | md5sig | nodelay | noopt | nopush | syncnt |
           user_timeout

       udp_socket_option() = cork

       sctp_socket_option() =
           adaption_layer | associnfo | auth_active_key | auth_asconf |
           auth_chunk | auth_key | auth_delete_key | autoclose |
           context | default_send_params | delayed_ack_time |
           disable_fragments | hmac_ident | events | explicit_eor |
           fragment_interleave | get_peer_addr_info | initmsg |
           i_want_mapped_v4_addr | local_auth_chunks | maxseg |
           maxburst | nodelay | partial_delivery_point |
           peer_addr_params | peer_auth_chunks | primary_addr |
           reset_streams | rtoinfo | set_peer_primary_addr | status |
           use_ext_recvinfo

       timeval() = #{sec := integer(), usec := integer()}

       ip_tos() =
           lowdelay | throughput | reliability | mincost | integer()

       ip_mreq() =
           #{multiaddr := ip4_address(),
             interface := any | ip4_address()}

       ip_mreq_source() =
           #{multiaddr := ip4_address(),
             interface := ip4_address(),
             sourceaddr := ip4_address()}

       ip_pmtudisc() = want | dont | do | probe

       ip_msfilter_mode() = include | exclude

       ip_msfilter() =
           #{multiaddr := ip4_address(),
             interface := ip4_address(),
             mode := ip_msfilter_mode(),
             slist := [ip4_address()]}

       ip_pktinfo() =
           #{ifindex := integer() >= 0,
             spec_dst := ip4_address(),
             addr := ip4_address()}

       ipv6_mreq() =
           #{multiaddr := ip6_address(), interface := integer() >= 0}

       ipv6_pmtudisc() = ip_pmtudisc()

       ipv6_pktinfo() = #{addr := ip6_address(), ifindex := integer()}

       sctp_assoc_id() = int32()

       sctp_sndrcvinfo() =
           #{stream := uint16(),
             ssn := uint16(),
             flags := uint16(),
             ppid := uint16(),
             context := uint16(),
             timetolive := uint16(),
             tsn := uint16(),
             cumtsn := uint16(),
             assoc_id := sctp_assoc_id()}

       sctp_event_subscribe() =
           #{data_in := boolean(),
             association := boolean(),
             address := boolean(),
             send_failure := boolean(),
             peer_error := boolean(),
             shutdown := boolean(),
             partial_delivery := boolean(),
             adaptation_layer := boolean(),
             authentication := boolean(),
             sender_dry := boolean()}

       sctp_assocparams() =
           #{assoc_id := sctp_assoc_id(),
             max_rxt := uint16(),
             num_peer_dests := uint16(),
             peer_rwnd := uint32(),
             local_rwnd := uint32(),
             cookie_life := uint32()}

       sctp_initmsg() =
           #{num_outstreams := uint16(),
             max_instreams := uint16(),
             max_attempts := uint16(),
             max_init_timeo := uint16()}

       sctp_rtoinfo() =
           #{assoc_id := sctp_assoc_id(),
             initial := uint32(),
             max := uint32(),
             min := uint32()}

       msghdr_flag() = ctrunc | eor | errqueue | oob | trunc

       msghdr_flags() = [msghdr_flag()]

       msghdr() =
           #{addr := sockaddr(),
             iov := [binary()],
             ctrl := [cmsghdr_recv()] | [cmsghdr_send()],
             flags := msghdr_flags()}

       cmsghdr_level() = socket | ip | ipv6 | integer()

       cmsghdr_type() =
           credentials | hoplevel | origdstaddr | pktinfo | recvtos |
           rights | timestamp | tos | ttl |
           integer()

       cmsghdr_recv() =
           #{level := socket, type := timestamp, data := timeval()} |
           #{level := socket, type := rights, data := binary()} |
           #{level := socket, type := credentials, data := binary()} |
           #{level := socket, type := integer(), data := binary()} |
           #{level := ip, type := tos, data := ip_tos()} |
           #{level := ip, type := recvtos, data := ip_tos()} |
           #{level := ip, type := ttl, data := integer()} |
           #{level := ip, type := recvttl, data := integer()} |
           #{level := ip, type := pktinfo, data := ip_pktinfo()} |
           #{level := ip, type := origdstaddr, data := sockaddr_in4()} |
           #{level := ip,
             type := recverr,
             data := extended_err() | binary()} |
           #{level := ip, type := integer(), data := binary()} |
           #{level := ipv6, type := hoplevel, data := integer()} |
           #{level := ipv6, type := pktinfo, data := ipv6_pktinfo()} |
           #{level := ipv6,
             type := recverr,
             data := extended_err() | binary()} |
           #{level := ipv6, type := tclass, data := integer()} |
           #{level := ipv6, type := integer(), data := binary()} |
           #{level := integer(), type := integer(), data := binary()}

       cmsghdr_send() =
           #{level := socket, type := timestamp, data := binary()} |
           #{level := socket, type := rights, data := binary()} |
           #{level := socket, type := credentials, data := binary()} |
           #{level := socket, type := integer(), data := binary()} |
           #{level := ip, type := tos, data := ip_tos() | binary()} |
           #{level := ip, type := ttl, data := integer() | binary()} |
           #{level := ip, type := integer(), data := binary()} |
           #{level := ipv6, type := tclass, data := integer()} |
           #{level := ipv6, type := integer(), data := binary()} |
           #{level := udp, type := integer(), data := binary()} |
           #{level := integer(), type := integer(), data := binary()}

       icmp_dest_unreach() =
           net_unreach | host_unreach | port_unreach | frag_needed |
           net_unknown | host_unknown |
           uint8()

       icmpv6_dest_unreach() =
           noroute | adm_prohibited | not_neighbour | addr_unreach |
           port_unreach | policy_fail | reject_route |
           uint8()

       ee_origin() = none | local | icmp | icmp6 | uint8()

       extended_err() =
           #{error := term(),
             origin := icmp,
             type := dest_unreach,
             code := icmp_dest_unreach(),
             info := uint32(),
             data := uint32(),
             offender := undefined | sockaddr()} |
           #{error := term(),
             origin := icmp,
             type := time_exceeded | uint8(),
             code := uint8(),
             info := uint32(),
             data := uint32(),
             offender := undefined | sockaddr()} |
           #{error := term(),
             origin := icmp6,
             type := dest_unreach,
             code := icmpv6_dest_unreach(),
             info := uint32(),
             data := uint32(),
             offender := undefined | sockaddr()} |
           #{error := term(),
             origin := icmp6,
             type := pkt_toobig | time_exceeded | uint8(),
             code := uint8(),
             info := uint32(),
             data := uint32(),
             offender := undefined | sockaddr()} |
           #{error := term(),
             origin := ee_origin(),
             type := uint8(),
             code := uint8(),
             info := uint32(),
             data := uint32(),
             offender := undefined | sockaddr()}

       uint8() = 0..255

       uint16() = 0..65535

       uint20() = 0..1048575

       uint32() = 0..4294967295

       int32() = -2147483648..2147483647

       supports_options_socket() = [{socket_option(), boolean()}]

       supports_options_ip() = [{ip_socket_option(), boolean()}]

       supports_options_ipv6() = [{ipv6_socket_option(), boolean()}]

       supports_options_tcp() = [{tcp_socket_option(), boolean()}]

       supports_options_udp() = [{udp_socket_option(), boolean()}]

       supports_options_sctp() = [{sctp_socket_option(), boolean()}]

       supports_options() =
           [{socket, supports_options_socket()} |
            {ip, supports_options_ip()} |
            {ipv6, supports_options_ipv6()} |
            {tcp, supports_options_tcp()} |
            {udp, supports_options_udp()} |
            {sctp, supports_options_sctp()}]

       supports_send_flags() = [{send_flag(), boolean()}]

       supports_recv_flags() = [{recv_flag(), boolean()}]

EXPORTS

       accept(LSocket) -> {ok, Socket} | {error, Reason}

       accept(LSocket, Timeout) -> {ok, Socket} | {error, Reason}

              Types:

                 LSocket = socket()
                 Timeout = timeout()
                 Socket = socket()
                 Reason = term()

              Accept a connection on a socket.

              This call is used with connection-based socket types (stream or seqpacket). It extracs  the  first
              pending connection request for the listen socket and returns the (newly) connected socket.

       accept(LSocket, Timeout :: nowait) ->
                 {ok, Socket} | {select, SelectInfo} | {error, Reason}

              Types:

                 LSocket = Socket = socket()
                 SelectInfo = select_info()
                 Reason = term()

              Accept a connection on a socket.

              This  call  is used with connection-based socket types (stream or seqpacket). It extracs the first
              pending connection request for the listen socket and returns the (newly) connected socket.

              In the case when there is no connections waiting, the function will return  with  the  SelectInfo.
              The  caller  can then await a select message, {'$socket', Socket, select, Info} (where Info is the
              ref field from the SelectInfo), when a client connects (a subsequent  call  to  accept  will  then
              return the socket).

       bind(Socket, Addr) -> {ok, Port} | {error, Reason}

              Types:

                 Socket = socket()
                 Addr = any | broadcast | loopback | sockaddr()
                 Port = port_number()
                 Reason = term()

              Bind a name to a socket.

              When  a  socket is created (with open), it has no address assigned to it. bind assigns the address
              specified by the Addr argument.

              The rules used for name binding vary between domains.

       cancel(Socket, SelectInfo) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 SelectInfo = select_info()
                 Reason = term()

              Cancel an asynchronous request.

              Call this function in order to cancel a previous asynchronous call to, e.g. recv/3.

       close(Socket) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 Reason = term()

              Closes the socket.

          Note:
              Note that for e.g. protocol = tcp, most implementations doing a close does not guarantee that  any
              data sent is delivered to the recipient before the close is detected at the remote side.

              One  way to handle this is to use the shutdown function (socket:shutdown(Socket, write)) to signal
              that no more data is to be sent and then wait for the read side of the socket to be closed.

       connect(Socket, SockAddr) -> ok | {error, Reason}

       connect(Socket, SockAddr, Timeout) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 SockAddr = sockaddr()
                 Timeout = timeout()
                 Reason = term()

              This function connects the socket to the address specied by the SockAddr argument.

       connect(Socket, SockAddr, Timeout :: nowait) ->
                  ok | {select, SelectInfo} | {error, Reason}

              Types:

                 Socket = socket()
                 SockAddr = sockaddr()
                 SelectInfo = select_info()
                 Reason = term()

              This function connects the socket to the address specied by the SockAddr argument.

              In the case when its not possible to immediately establish a connection, the function will  return
              with the SelectInfo. The caller can then await a select message, {'$socket', Socket, select, Info}
              (where Info is the ref field from the SelectInfo, a subsequent call to connect will then establish
              the connection).

       getopt(Socket, Level :: otp, Key :: otp_socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: socket, Key :: socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: ip, Key :: ip_socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: ipv6, Key :: ipv6_socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: tcp, Key :: tcp_socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: udp, Key :: udp_socket_option()) ->
                 {ok, Value} | {error, Reason}

       getopt(Socket, Level :: sctp, Key :: sctp_socket_option()) ->
                 {ok, Value} | {error, Reason}

              Types:

                 Socket = socket()
                 Value = Reason = term()

              Get an option on a socket.

              What  properties are valid depend both on Level and on what kind of socket it is (domain, type and
              protocol).

              See the socket options chapter of the users guide for more info.

          Note:
              Not all options are valid on all platforms. That is, even if "we" support an option, that does not
              mean that the underlying OS does.

       getopt(Socket, Level, Key) -> ok | {ok, Value} | {error, Reason}

              Types:

                 Socket = socket()
                 Level = integer()
                 Key = {NativeOpt, ValueSize}
                 NativeOpt = integer()
                 ValueSize = int | bool | integer() >= 0
                 Value = Reason = term()

              Get an option on a socket.

              When specifying Level as an integer, and therefor using "native mode", it is *currently* up to the
              caller to know how to interpret the result.

              For more info, see getopt above.

       info(Socket) -> socket_info()

              Types:

                 Socket = socket()

              Get miscellaneous info about the socket.

              The function returns a map with each info item as a key-value binding. It reflects  the  "current"
              state of the socket.

          Note:
              In  order  to ensure data integrity, mutex'es are taken when needed. So, do not call this function
              often.

       listen(Socket) -> ok | {error, Reason}

       listen(Socket, Backlog) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 Backlog = integer() >= 1
                 Reason = term()

              Listen for connections on a socket.

       open(Domain, Type) -> {ok, Socket} | {error, Reason}

       open(Domain, Type, Protocol) -> {ok, Socket} | {error, Reason}

       open(Domain, Type, Protocol, Extra) ->
               {ok, Socket} | {error, Reason}

              Types:

                 Domain = domain()
                 Type = type()
                 Protocol = default | protocol()
                 Extra = map()
                 Socket = socket()
                 Reason = term()

              Creates an endpoint (socket) for communication.

              For some types there is a default protocol, indicated by default, which  it  may  be  possible  to
              specify. And for Domain = local, if a protocol is pecified, it must be default.

              The  Extra  argument  is  intended  for  "obscure" options. Currently the only supported option is
              netns, which is only supported on the linux platform.

          Note:
              It may not be possible to specify the default protocol (except when Domain = local). We need to be
              able to retreive the resulting protocol, which is not possble on all platforms.

       peername(Socket) -> {ok, SockAddr} | {error, Reason}

              Types:

                 Socket = socket()
                 SockAddr = sockaddr()
                 Reason = term()

              Returns the address of the peer connected to the socket.

       recv(Socket) -> {ok, Data} | {error, Reason}

       recv(Socket, Length) -> {ok, Data} | {error, Reason}

       recv(Socket, Length, Flags) -> {ok, Data} | {error, Reason}

       recv(Socket, Length, Timeout) -> {ok, Data} | {error, Reason}

       recv(Socket, Length, Flags, Timeout) ->
               {ok, Data} | {error, Reason}

              Types:

                 Socket = socket()
                 Length = integer() >= 0
                 Flags = recv_flags()
                 Timeout = timeout()
                 Data = binary()
                 Reason = term()

              Receive a message from a socket.

              There  is  a  special  case  for  the argument Length. If it is set to zero (0), it means "give me
              everything you currently have".

       recv(Socket, Length, Timeout :: nowait) ->
               {ok, Data} |
               {select, SelectInfo} |
               {ok, {Data, SelectInfo}} |
               {error, Reason}

       recv(Socket, Length, Flags, Timeout :: nowait) ->
               {ok, Data} |
               {select, SelectInfo} |
               {ok, {Data, SelectInfo}} |
               {error, Reason}

              Types:

                 Socket = socket()
                 Length = integer() >= 0
                 Flags = recv_flags()
                 Data = binary()
                 SelectInfo = select_info()
                 Reason = term()

              Receive a message from a socket.

              There is a special case for the argument Length. If it is set to  zero  (0),  it  means  "give  me
              everything you currently have".

              In  the  case  when  there  is  no data waiting, the function will return with the SelectInfo. The
              caller can then await a select message, {'$socket', Socket, select, Info} (where Info is  the  ref
              field  from the SelectInfo), when data has arrived (a subsequent call to recv will then return the
              data).

              Note that if a length (> 0) is specified, and only part of that amount of data is  available,  the
              function  will  return with that data and the SelectInfo (if the caller don't want to wait for the
              remaining data, it must immediately call the cancel/2 function.)

       recvfrom(Socket) -> {ok, {Source, Data}} | {error, Reason}

       recvfrom(Socket, BufSz) -> {ok, {Source, Data}} | {error, Reason}

       recvfrom(Socket, Flags, Timeout) ->
                   {ok, {Source, Data}} | {error, Reason}

       recvfrom(Socket, BufSz, Flags) ->
                   {ok, {Source, Data}} | {error, Reason}

       recvfrom(Socket, BufSz, Timeout) ->
                   {ok, {Source, Data}} | {error, Reason}

       recvfrom(Socket, BufSz, Flags, Timeout) ->
                   {ok, {Source, Data}} | {error, Reason}

              Types:

                 Socket = socket()
                 BufSz = integer() >= 0
                 Flags = recv_flags()
                 Timeout = timeout()
                 Source = sockaddr() | undefined
                 Data = binary()
                 Reason = term()

              Receive a message from a socket.

              This function reads "messages", which means that regardless of  how  much  we  want  to  read,  it
              returns when we get a message (if the buffer size is too small, the message will be truncated).

              The  BufSz argument basically defines the size of the receive buffer. By setting the value to zero
              (0), the configured size (setopt with Level = otp and Key = rcvbuf) is used.

              It may be impossible to know what (buffer) size is appropriate "in advance", and in those cases it
              may  be convenient to use the (recv) 'peek' flag. When this flag is provided, the message is *not*
              "consumed" from the underlying buffers, so another recvfrom call is needed, possibly with  a  then
              adjusted buffer size.

       recvfrom(Socket, Flags, Timeout :: nowait) ->
                   {ok, {Source, Data}} |
                   {select, SelectInfo} |
                   {error, Reason}

       recvfrom(Socket, BufSz, Timeout :: nowait) ->
                   {ok, {Source, Data}} |
                   {select, SelectInfo} |
                   {error, Reason}

       recvfrom(Socket, BufSz, Flags, Timeout :: nowait) ->
                   {ok, {Source, Data}} |
                   {select, SelectInfo} |
                   {error, Reason}

              Types:

                 Socket = socket()
                 BufSz = integer() >= 0
                 Flags = recv_flags()
                 Source = sockaddr() | undefined
                 Data = binary()
                 SelectInfo = select_info()
                 Reason = term()

              Receive a message from a socket.

              This  function  reads  "messages",  which  means  that  regardless of how much we want to read, it
              returns when we get a message (if the buffer size is too small, the message will be truncated).

              The BufSz argument basically defines the size of the receive buffer. By setting the value to  zero
              (0), the configured size (setopt with Level = otp and Key = rcvbuf) is used.

              It may be impossible to know what (buffer) size is appropriate "in advance", and in those cases it
              may be convenient to use the (recv) 'peek' flag. When this flag is provided, the message is  *not*
              "consumed"  from  the underlying buffers, so another recvfrom call is needed, possibly with a then
              adjusted buffer size.

              In the case when there is no data waiting, the function  will  return  with  the  SelectInfo.  The
              caller  can  then await a select message, {'$socket', Socket, select, Info} (where Info is the ref
              field from the SelectInfo), when data has arrived (a subsequent call to recvfrom will then  return
              the data).

       recvmsg(Socket) -> {ok, MsgHdr} | {error, Reason}

       recvmsg(Socket, Flags) -> {ok, MsgHdr} | {error, Reason}

       recvmsg(Socket, Timeout) -> {ok, MsgHdr} | {error, Reason}

       recvmsg(Socket, Flags, Timeout) -> {ok, MsgHdr} | {error, Reason}

       recvmsg(Socket, BufSz, CtrlSz) -> {ok, MsgHdr} | {error, Reason}

       recvmsg(Socket, BufSz, CtrlSz, Flags, Timeout) ->
                  {ok, MsgHdr} | {error, Reason}

              Types:

                 Socket = socket()
                 BufSz = CtrlSz = integer() >= 0
                 Flags = recv_flags()
                 Timeout = timeout()
                 MsgHdr = msghdr()
                 Reason = term()

              Receive a message from a socket.

              This  function  reads  "messages",  which  means  that  regardless of how much we want to read, it
              returns when we get a message.

              The message will be delivered in the form of a msghdr(), which may contain the source address  (if
              socket  not connected), a list of cmsghdr_recv() (depends on what socket options have been set and
              what the protocol and platform supports) and also a set of flags, providing further info about the
              read.

              The  BufSz argument basically defines the size of the receive buffer. By setting the value to zero
              (0), the configured size (setopt with Level = otp and Key = rcvbuf) is used.

              The CtrlSz argument basically defines the size of the receive buffer for the control messages.  By
              setting the value to zero (0), the configured size (setopt with Level = otp) is used.

              It may be impossible to know what (buffer) size is appropriate "in advance", and in those cases it
              may be convenient to use the (recv) 'peek' flag. When this flag is provided, the message is  *not*
              "consumed"  from  the  underlying buffers, so another recvmsg call is needed, possibly with a then
              adjusted buffer size.

       recvmsg(Socket, Timeout :: nowait) ->
                  {ok, MsgHdr} | {select, SelectInfo} | {error, Reason}

       recvmsg(Socket, Flags, Timeout :: nowait) ->
                  {ok, MsgHdr} | {select, SelectInfo} | {error, Reason}

       recvmsg(Socket, BufSz, CtrlSz, Flags, Timeout :: nowait) ->
                  {ok, MsgHdr} | {select, SelectInfo} | {error, Reason}

              Types:

                 Socket = socket()
                 BufSz = CtrlSz = integer() >= 0
                 Flags = recv_flags()
                 MsgHdr = msghdr()
                 SelectInfo = select_info()
                 Reason = term()

              Receive a message from a socket.

              This function reads "messages", which means that regardless of  how  much  we  want  to  read,  it
              returns when we get a message.

              The  message will be delivered in the form of a msghdr(), which may contain the source address (if
              socket not connected), a list of cmsghdr_recv() (depends on what socket options have been set  and
              what the protocol and platform supports) and also a set of flags, providing further info about the
              read.

              The BufSz argument basically defines the size of the receive buffer. By setting the value to  zero
              (0), the configured size (setopt with Level = otp and Key = rcvbuf) is used.

              The  CtrlSz argument basically defines the size of the receive buffer for the control messages. By
              setting the value to zero (0), the configured size (setopt with Level = otp) is used.

              It may be impossible to know what (buffer) size is appropriate "in advance", and in those cases it
              may  be convenient to use the (recv) 'peek' flag. When this flag is provided, the message is *not*
              "consumed" from the underlying buffers, so another recvmsg call is needed, possibly  with  a  then
              adjusted buffer size.

              In  the  case  when  there  is  no data waiting, the function will return with the SelectInfo. The
              caller can then await a select message, {'$socket', Socket, select, Info} (where Info is  the  ref
              field  from  the SelectInfo), when data has arrived (a subsequent call to recvmsg will then return
              the data).

       send(Socket, Data) -> ok | {error, Reason}

       send(Socket, Data, Flags) -> ok | {error, Reason}

       send(Socket, Data, Timeout) -> ok | {error, Reason}

       send(Socket, Data, Flags, Timeout) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 Data = iodata()
                 Flags = send_flags()
                 Timeout = timeout()
                 Reason = term()

              Send a message on a connected socket.

       send(Socket, Data, Timeout :: nowait) ->
               ok |
               {select, SelectInfo} |
               {ok, {RestData, SelectInfo}} |
               {error, Reason}

       send(Socket, Data, Flags, Timeout :: nowait) ->
               ok |
               {select, SelectInfo} |
               {ok, {RestData, SelectInfo}} |
               {error, Reason}

              Types:

                 Socket = socket()
                 Data = iodata()
                 Flags = send_flags()
                 RestData = binary()
                 SelectInfo = select_info()
                 Reason = term()

              Send a message on a connected socket.

              In the case when there is no room in the (system-) buffers, the  function  will  return  with  the
              SelectInfo.  The  caller can then await a select message, {'$socket', Socket, select, Info} (where
              Info is the ref field from the SelectInfo), when there is room for more data (a subsequent call to
              send will then send the data).

              Note  that  if not all the data was sent, the function will return with the remaining data and the
              SelectInfo (if the caller don't want to wait to be able to send the rest,  it  should  immediately
              call the cancel/2 function.)

       sendmsg(Socket, MsgHdr) -> ok | {error, Reason}

       sendmsg(Socket, MsgHdr, Flags) -> ok | {error, Reason}

       sendmsg(Socket, MsgHdr, Timeout) -> ok | {error, Reason}

       sendmsg(Socket, MsgHdr, Flags, Timeout) ->
                  ok | {ok, Remaining} | {error, Reason}

              Types:

                 Socket = socket()
                 MsgHdr = msghdr()
                 Flags = send_flags()
                 Timeout = timeout()
                 Remaining = erlang:iovec()
                 Reason = term()

              Send  a  message on a socket. The destination, if needed (socket not connected) is provided in the
              MsgHdr, which also contains the message to send, The MsgHdr may also contain an list  of  optional
              cmsghdr_send() (depends on what the protocol and platform supports).

              Unlike the send function, this one sends one message. This means that if, for whatever reason, its
              not possible to send the message in one go, the function will instead return  with  the  remaining
              data  ({ok,  Remaining}). Thereby leaving it up to the caller to decide what to do (retry with the
              remaining data of give up).

       sendmsg(Socket, MsgHdr, Timeout :: nowait) ->
                  ok | {select, SelectInfo} | {error, Reason}

       sendmsg(Socket, MsgHdr, Flags, Timeout :: nowait) ->
                  ok |
                  {ok, Remaining} |
                  {select, SelectInfo} |
                  {error, Reason}

              Types:

                 Socket = socket()
                 MsgHdr = msghdr()
                 Flags = send_flags()
                 Remaining = erlang:iovec()
                 SelectInfo = select_info()
                 Reason = term()

              Send a message on a socket. The destination, if needed (socket not connected) is provided  in  the
              MsgHdr,  which  also contains the message to send, The MsgHdr may also contain an list of optional
              cmsghdr_send() (depends on what the protocol and platform supports).

              Unlike the send function, this one sends one message. This means that if, for whatever reason, its
              not  possible  to  send the message in one go, the function will instead return with the remaining
              data ({ok, Remaining}). Thereby leaving it up to the caller to decide what to do (retry  with  the
              remaining data of give up).

              In  the  case  when  there  is no room in the (system-) buffers, the function will return with the
              SelectInfo. The caller can then await a select message, {'$socket', Socket, select,  Info}  (where
              Info is the ref field from the SelectInfo), when there is room for more data (a subsequent call to
              sendmsg will then send the data).

       sendto(Socket, Data, Dest) -> ok | {error, Reason}

       sendto(Socket, Data, Dest, Flags) -> ok | {error, Reason}

       sendto(Socket, Data, Dest, Timeout) -> ok | {error, Reason}

       sendto(Socket, Data, Dest, Flags, Timeout) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 Data = binary()
                 Dest = sockaddr()
                 Flags = send_flags()
                 Timeout = timeout()
                 Reason = term()

              Send a message on a socket, to the specified destination.

       sendto(Socket, Data, Dest, Timeout :: nowait) ->
                 ok | {select, SelectInfo} | {error, Reason}

       sendto(Socket, Data, Dest, Flags, Timeout :: nowait) ->
                 ok | {select, SelectInfo} | {error, Reason}

              Types:

                 Socket = socket()
                 Data = binary()
                 Dest = sockaddr()
                 Flags = send_flags()
                 SelectInfo = select_info()
                 Reason = term()

              Send a message on a socket, to the specified destination.

              In the case when there is no room in the (system-) buffers, the  function  will  return  with  the
              SelectInfo.  The  caller can then await a select message, {'$socket', Socket, select, Info} (where
              Info is the ref field from the SelectInfo), when there is room for more data (a subsequent call to
              sendto will then send the data).

       setopt(Socket, Level :: otp, Key :: otp_socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: socket, Key :: socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: ip, Key :: ip_socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: ipv6, Key :: ipv6_socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: tcp, Key :: tcp_socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: udp, Key :: udp_socket_option(), Value) ->
                 ok | {error, Reason}

       setopt(Socket, Level :: sctp, Key :: sctp_socket_option(), Value) ->
                 ok | {error, Reason}

              Types:

                 Socket = socket()
                 Value = Reason = term()

              Set options on a socket.

              What  properties are valid depend both on Level and on what kind of socket it is (domain, type and
              protocol).

              See the socket options chapter of the users guide for more info.

          Note:
              Not all options are valid on all platforms. That is, even if "we" support an option, that does not
              mean that the underlying OS does.

          Note:
              Sockets  are  set  'non-blocking'  when  created,  so  this option is *not* available (as it would
              adversely effect the Erlang VM to set a socket 'blocking').

       setopt(Socket, Level, Key, Value) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 Level = Key = integer() >= 0
                 Value = binary()
                 Reason = term()

              Set options on a socket.

              When specifying Level as an integer, and therefor using "native mode", it is *currently* up to the
              caller to know how to encode the Value.

              For more info, see setopt above.

       shutdown(Socket, How) -> ok | {error, Reason}

              Types:

                 Socket = socket()
                 How = shutdown_how()
                 Reason = term()

              Shut down all or part of a full-duplex connection.

       sockname(Socket) -> {ok, SockAddr} | {error, Reason}

              Types:

                 Socket = socket()
                 SockAddr = sockaddr()
                 Reason = term()

              Returns the current address to which the socket is bound.

       supports() ->
                   [{options, supports_options()} |
                    {sctp, boolean()} |
                    {ipv6, boolean()} |
                    {local, boolean()} |
                    {send_flags, supports_send_flags()} |
                    {recv_flags, supports_recv_flags()}]

       supports(Key1 :: options) -> supports_options()

       supports(Key1 :: sctp) -> boolean()

       supports(Key1 :: ipv6) -> boolean()

       supports(Key1 :: local) -> boolean()

       supports(Key1 :: send_flags) -> supports_send_flags()

       supports(Key1 :: recv_flags) -> supports_recv_flags()

       supports(Key1) -> false

       supports(Key1 :: options, Level :: socket) ->
                   supports_options_socket()

       supports(Key1 :: options, Level :: ip) -> supports_options_ip()

       supports(Key1 :: options, Level :: ipv6) ->
                   supports_options_ipv6()

       supports(Key1 :: options, Level :: tcp) -> supports_options_tcp()

       supports(Key1 :: options, Level :: udp) -> supports_options_udp()

       supports(Key1 :: options, Level :: sctp) ->
                   supports_options_sctp()

       supports(Key1 :: send_flags, SendFlag :: send_flag()) -> boolean()

       supports(Key1 :: recv_flags, RecvFlag :: recv_flag()) -> boolean()

       supports(Key1, Key2) -> false

       supports(Key1 :: options, Level :: socket, Opt :: socket_option()) ->
                   boolean()

       supports(Key1 :: options, Level :: ip, Opt :: ip_socket_option()) ->
                   boolean()

       supports(Key1 :: options,
                Level :: ipv6,
                Opt :: ipv6_socket_option()) ->
                   boolean()

       supports(Key1 :: options,
                Level :: tcp,
                Opt :: tcp_socket_option()) ->
                   boolean()

       supports(Key1 :: options,
                Level :: udp,
                Opt :: udp_socket_option()) ->
                   boolean()

       supports(Key1 :: options,
                Level :: sctp,
                Opt :: sctp_socket_option()) ->
                   boolean()

       supports(Key1, Key2, Key3) -> false

              Types:

                 Key1 = Key2 = Key3 = term()

              This function intends to retreive information about what the platform supports. Such as if SCTP is
              supported. Or which socket options are supported.

EXAMPLES

       client(Addr, SAddr, SPort) ->
          {ok, Sock} = socket:open(inet, stream, tcp),
          {ok, _} = socket:bind(Sock, #{family => inet,
                                        addr   => Addr}),
          ok = socket:connect(Sock, #{family => inet,
                                      addr   => SAddr,
                             port   => SPort}),
          Msg = list_to_binary("hello"),
          ok = socket:send(Sock, Msg),
          ok = socket:shutdown(Sock, write),
          {ok, Msg} = socket:recv(Sock),
          ok = socket:close(Sock).

       server(Addr, Port) ->
          {ok, LSock} = socket:open(inet, stream, tcp),
          {ok, _} = socket:bind(LSock, #{family => inet,
                                         port   => Port,
                                addr   => Addr}),
          ok = socket:listen(LSock),
          {ok, Sock} = socket:accept(LSock),
          {ok, Msg} = socket:recv(Sock),
          ok = socket:send(Sock, Msg),
          ok = socket:shutdown(Sock, write),
          ok = socket:close(Sock),
          ok = socket:close(LSock).