Provided by: erlang-manpages_22.2.7+dfsg-1_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).