Provided by: erlang-manpages_20.2.2+dfsg-1ubuntu2_all bug

NAME

       gen_tcp - Interface to TCP/IP sockets.

DESCRIPTION

       This module provides functions for communicating with sockets using the TCP/IP protocol.

       The following code fragment is a simple example of a client connecting to a server at port
       5678, transferring a binary, and closing the connection:

       client() ->
           SomeHostInNet = "localhost", % to make it runnable on one machine
           {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
                                        [binary, {packet, 0}]),
           ok = gen_tcp:send(Sock, "Some Data"),
           ok = gen_tcp:close(Sock).

       At the other end, a server is listening on port 5678, accepts the connection, and receives
       the binary:

       server() ->
           {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
                                               {active, false}]),
           {ok, Sock} = gen_tcp:accept(LSock),
           {ok, Bin} = do_recv(Sock, []),
           ok = gen_tcp:close(Sock),
           ok = gen_tcp:close(LSock),
           Bin.

       do_recv(Sock, Bs) ->
           case gen_tcp:recv(Sock, 0) of
               {ok, B} ->
                   do_recv(Sock, [Bs, B]);
               {error, closed} ->
                   {ok, list_to_binary(Bs)}
           end.

       For more examples, see section Examples.

DATA TYPES

       option() =
           {active, true | false | once | -32768..32767} |
           {buffer, integer() >= 0} |
           {delay_send, boolean()} |
           {deliver, port | term} |
           {dontroute, boolean()} |
           {exit_on_close, boolean()} |
           {header, integer() >= 0} |
           {high_msgq_watermark, integer() >= 1} |
           {high_watermark, integer() >= 0} |
           {keepalive, boolean()} |
           {linger, {boolean(), integer() >= 0}} |
           {low_msgq_watermark, integer() >= 1} |
           {low_watermark, integer() >= 0} |
           {mode, list | binary} |
           list |
           binary |
           {nodelay, boolean()} |
           {packet,
            0 |
            1 |
            2 |
            4 |
            raw |
            sunrm |
            asn1 |
            cdr |
            fcgi |
            line |
            tpkt |
            http |
            httph |
            http_bin |
            httph_bin} |
           {packet_size, integer() >= 0} |
           {priority, integer() >= 0} |
           {raw,
            Protocol :: integer() >= 0,
            OptionNum :: integer() >= 0,
            ValueBin :: binary()} |
           {recbuf, integer() >= 0} |
           {reuseaddr, boolean()} |
           {send_timeout, integer() >= 0 | infinity} |
           {send_timeout_close, boolean()} |
           {show_econnreset, boolean()} |
           {sndbuf, integer() >= 0} |
           {tos, integer() >= 0} |
           {ipv6_v6only, boolean()}

       option_name() =
           active |
           buffer |
           delay_send |
           deliver |
           dontroute |
           exit_on_close |
           header |
           high_msgq_watermark |
           high_watermark |
           keepalive |
           linger |
           low_msgq_watermark |
           low_watermark |
           mode |
           nodelay |
           packet |
           packet_size |
           priority |
           {raw,
            Protocol :: integer() >= 0,
            OptionNum :: integer() >= 0,
            ValueSpec ::
                (ValueSize :: integer() >= 0) | (ValueBin :: binary())} |
           recbuf |
           reuseaddr |
           send_timeout |
           send_timeout_close |
           show_econnreset |
           sndbuf |
           tos |
           ipv6_v6only

       connect_option() =
           {ip, inet:socket_address()} |
           {fd, Fd :: integer() >= 0} |
           {ifaddr, inet:socket_address()} |
           inet:address_family() |
           {port, inet:port_number()} |
           {tcp_module, module()} |
           option()

       listen_option() =
           {ip, inet:socket_address()} |
           {fd, Fd :: integer() >= 0} |
           {ifaddr, inet:socket_address()} |
           inet:address_family() |
           {port, inet:port_number()} |
           {backlog, B :: integer() >= 0} |
           {tcp_module, module()} |
           option()

       socket()

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

EXPORTS

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

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

              Types:

                 ListenSocket = socket()
                   Returned by listen/2.
                 Timeout = timeout()
                 Socket = socket()
                 Reason = closed | timeout | system_limit | inet:posix()

              Accepts  an  incoming  connection  request  on a listening socket. Socket must be a
              socket returned from listen/2. Timeout specifies a time-out value in  milliseconds.
              Defaults to infinity.

              Returns:

                * {ok, Socket} if a connection is established

                * {error, closed} if ListenSocket is closed

                * {error, timeout} if no connection is established within the specified time

                * {error, system_limit} if all available ports in the Erlang emulator are in use

                * A  POSIX  error value if something else goes wrong, see inet(3erl) for possible
                  error values

              Packets can be sent to the returned socket Socket using send/2. Packets  sent  from
              the  peer  are  delivered  as  messages (unless {active, false} is specified in the
              option list for the listening socket,  in  which  case  packets  are  retrieved  by
              calling recv/2):

              {tcp, Socket, Data}

          Note:
              The  accept  call  does  not have to be issued from the socket owner process. Using
              version 5.5.3 and higher of the emulator, multiple simultaneous accept calls can be
              issued  from  different  processes,  which  allows for a pool of acceptor processes
              handling incoming connections.

       close(Socket) -> ok

              Types:

                 Socket = socket()

              Closes a TCP socket.

              Note that in most implementations of TCP, doing a close does not guarantee that any
              data  sent is delivered to the recipient before the close is detected at the remote
              side. If you want to guarantee delivery of the data to the recipient there are  two
              common ways to achieve this.

                * Use gen_tcp:shutdown(Sock, write) to signal that no more data is to be sent and
                  wait for the read side of the socket to be closed.

                * Use the socket option {packet, N} (or something similar) to  make  it  possible
                  for the receiver to close the connection when it knowns it has received all the
                  data.

       connect(Address, Port, Options) -> {ok, Socket} | {error, Reason}

       connect(Address, Port, Options, Timeout) ->
                  {ok, Socket} | {error, Reason}

              Types:

                 Address = inet:socket_address() | inet:hostname()
                 Port = inet:port_number()
                 Options = [connect_option()]
                 Timeout = timeout()
                 Socket = socket()
                 Reason = inet:posix()

              Connects to a server on TCP port Port on the host with IP address Address. Argument
              Address can be a hostname or an IP address.

              The following options are available:

                {ip, Address}:
                  If  the  host  has  many network interfaces, this option specifies which one to
                  use.

                {ifaddr, Address}:
                  Same as {ip, Address}. If the host has many  network  interfaces,  this  option
                  specifies which one to use.

                {fd, integer() >= 0}:
                  If  a  socket has somehow been connected without using gen_tcp, use this option
                  to  pass  the  file  descriptor  for  it.  If  {ip,  Address}   and/or   {port,
                  port_number()}  is  combined with this option, the fd is bound to the specified
                  interface and port before connecting. If these options are not specified, it is
                  assumed that the fd is already bound appropriately.

                inet:
                  Sets up the socket for IPv4.

                inet6:
                  Sets up the socket for IPv6.

                local:
                  Sets up a Unix Domain Socket. See inet:local_address()

                {port, Port}:
                  Specifies which local port number to use.

                {tcp_module, module()}:
                  Overrides  which  callback  module  is  used. Defaults to inet_tcp for IPv4 and
                  inet6_tcp for IPv6.

                Opt:
                  See inet:setopts/2.

              Packets can be sent to the returned socket Socket using send/2. Packets  sent  from
              the peer are delivered as messages:

              {tcp, Socket, Data}

              If  the  socket  is  in  {active,  N} mode (see inet:setopts/2 for details) and its
              message counter drops to 0, the following message is delivered to indicate that the
              socket has transitioned to passive ({active, false}) mode:

              {tcp_passive, Socket}

              If the socket is closed, the following message is delivered:

              {tcp_closed, Socket}

              If  an  error  occurs  on  the  socket,  the following message is delivered (unless
              {active, false} is specified in the option list  for  the  socket,  in  which  case
              packets are retrieved by calling recv/2):

              {tcp_error, Socket, Reason}

              The  optional  Timeout  parameter specifies a time-out in milliseconds. Defaults to
              infinity.

          Note:
              The default values for options specified to connect can be affected by  the  Kernel
              configuration parameter inet_default_connect_options. For details, see inet(3erl).

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

              Types:

                 Socket = socket()
                 Pid = pid()
                 Reason = closed | not_owner | badarg | inet:posix()

              Assigns  a  new  controlling  process Pid to Socket. The controlling process is the
              process that receives messages from the socket. If called by any other process than
              the  current  controlling  process,  {error, not_owner} is returned. If the process
              identified by Pid is not an  existing  local  pid,  {error,  badarg}  is  returned.
              {error, badarg} may also be returned in some cases when Socket is closed during the
              execution of this function.

              If the socket is set in active mode, this function will transfer  any  messages  in
              the  mailbox  of the caller to the new controlling process. If any other process is
              interacting with the socket while the transfer is happening, the transfer  may  not
              work  correctly  and  messages  may  remain  in  the caller's mailbox. For instance
              changing the sockets active mode before the transfere is complete may cause this.

       listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}

              Types:

                 Port = inet:port_number()
                 Options = [listen_option()]
                 ListenSocket = socket()
                 Reason = system_limit | inet:posix()

              Sets up a socket to listen on port Port on the local host.

              If Port == 0, the underlying OS assigns an available port number,  use  inet:port/1
              to retrieve it.

              The following options are available:

                list:
                  Received Packet is delivered as a list.

                binary:
                  Received Packet is delivered as a binary.

                {backlog, B}:
                  B  is  an  integer  >= 0. The backlog value defines the maximum length that the
                  queue of pending connections can grow to. Defaults to 5.

                {ip, Address}:
                  If the host has many network interfaces, this option  specifies  which  one  to
                  listen on.

                {port, Port}:
                  Specifies which local port number to use.

                {fd, Fd}:
                  If  a  socket has somehow been connected without using gen_tcp, use this option
                  to pass the file descriptor for it.

                {ifaddr, Address}:
                  Same as {ip, Address}. If the host has many  network  interfaces,  this  option
                  specifies which one to use.

                inet6:
                  Sets up the socket for IPv6.

                inet:
                  Sets up the socket for IPv4.

                {tcp_module, module()}:
                  Overrides  which  callback  module  is  used. Defaults to inet_tcp for IPv4 and
                  inet6_tcp for IPv6.

                Opt:
                  See inet:setopts/2.

              The returned socket ListenSocket should be used in calls to  accept/1,2  to  accept
              incoming connection requests.

          Note:
              The  default  values  for options specified to listen can be affected by the Kernel
              configuration parameter inet_default_listen_options. For details, see inet(3erl).

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

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

              Types:

                 Socket = socket()
                 Length = integer() >= 0
                 Timeout = timeout()
                 Packet = string() | binary() | HttpPacket
                 Reason = closed | inet:posix()
                 HttpPacket = term()
                   See the description of HttpPacket in erlang:decode_packet/3 in ERTS.

              Receives a packet from a socket in passive mode. A closed socket  is  indicated  by
              return value {error, closed}.

              Argument  Length  is only meaningful when the socket is in raw mode and denotes the
              number of bytes to read. If Length is 0,  all  available  bytes  are  returned.  If
              Length  >  0,  exactly  Length bytes are returned, or an error; possibly discarding
              less than Length bytes of data when the socket is closed from the other side.

              The optional Timeout parameter specifies a time-out in  milliseconds.  Defaults  to
              infinity.

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

              Types:

                 Socket = socket()
                 Packet = iodata()
                 Reason = closed | inet:posix()

              Sends a packet on a socket.

              There  is  no  send  call with a time-out option, use socket option send_timeout if
              time-outs are desired. See section Examples.

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

              Types:

                 Socket = socket()
                 How = read | write | read_write
                 Reason = inet:posix()

              Closes a socket in one or two directions.

              How == write means closing the  socket  for  writing,  reading  from  it  is  still
              possible.

              If How == read or there is no outgoing data buffered in the Socket port, the socket
              is shut down immediately and any error encountered is returned in Reason.

              If there is data buffered in the socket port, the attempt to shutdown the socket is
              postponed  until  that  data  is  written  to the kernel socket send buffer. If any
              errors are encountered, the socket is closed and {error, closed} is returned on the
              next recv/2 or send/2.

              Option  {exit_on_close,  false}  is  useful  if the peer has done a shutdown on the
              write side.

EXAMPLES

       The following example illustrates use of option  {active,once}  and  multiple  accepts  by
       implementing  a  server as a number of worker processes doing accept on a single listening
       socket. Function start/2 takes the number of worker processes and the port number on which
       to  listen  for incoming connections. If LPort is specified as 0, an ephemeral port number
       is used, which is why the start function returns the actual port number allocated:

       start(Num,LPort) ->
           case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
               {ok, ListenSock} ->
                   start_servers(Num,ListenSock),
                   {ok, Port} = inet:port(ListenSock),
                   Port;
               {error,Reason} ->
                   {error,Reason}
           end.

       start_servers(0,_) ->
           ok;
       start_servers(Num,LS) ->
           spawn(?MODULE,server,[LS]),
           start_servers(Num-1,LS).

       server(LS) ->
           case gen_tcp:accept(LS) of
               {ok,S} ->
                   loop(S),
                   server(LS);
               Other ->
                   io:format("accept returned ~w - goodbye!~n",[Other]),
                   ok
           end.

       loop(S) ->
           inet:setopts(S,[{active,once}]),
           receive
               {tcp,S,Data} ->
                   Answer = process(Data), % Not implemented in this example
                   gen_tcp:send(S,Answer),
                   loop(S);
               {tcp_closed,S} ->
                   io:format("Socket ~w closed [~w]~n",[S,self()]),
                   ok
           end.

       Example of a simple client:

       client(PortNo,Message) ->
           {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
                                                           {packet,2}]),
           gen_tcp:send(Sock,Message),
           A = gen_tcp:recv(Sock,0),
           gen_tcp:close(Sock),
           A.

       The send call does not accept a time-out option  because  time-outs  on  send  is  handled
       through  socket  option send_timeout. The behavior of a send operation with no receiver is
       mainly defined by the underlying TCP stack and the network infrastructure. To  write  code
       that  handles a hanging receiver that can eventually cause the sender to hang on a send do
       like the following.

       Consider a process that receives data from a client process to be forwarded to a server on
       the  network.  The  process is connected to the server through TCP/IP and does not get any
       acknowledge for each message it sends, but has to rely on  the  send  time-out  option  to
       detect  that  the  other  end  is  unresponsive.  Option  send_timeout  can  be  used when
       connecting:

       ...
       {ok,Sock} = gen_tcp:connect(HostAddress, Port,
                                   [{active,false},
                                    {send_timeout, 5000},
                                    {packet,2}]),
                       loop(Sock), % See below
       ...

       In the loop where requests are handled, send time-outs can now be detected:

       loop(Sock) ->
           receive
               {Client, send_data, Binary} ->
                   case gen_tcp:send(Sock,[Binary]) of
                       {error, timeout} ->
                           io:format("Send timeout, closing!~n",
                                     []),
                           handle_send_timeout(), % Not implemented here
                           Client ! {self(),{error_sending, timeout}},
                           %% Usually, it's a good idea to give up in case of a
                           %% send timeout, as you never know how much actually
                           %% reached the server, maybe only a packet header?!
                           gen_tcp:close(Sock);
                       {error, OtherSendError} ->
                           io:format("Some other error on socket (~p), closing",
                                     [OtherSendError]),
                           Client ! {self(),{error_sending, OtherSendError}},
                           gen_tcp:close(Sock);
                       ok ->
                           Client ! {self(), data_sent},
                           loop(Sock)
                   end
           end.

       Usually it suffices to detect time-outs on receive, as most protocols include some sort of
       acknowledgment  from  the  server,  but  if  the  protocol  is  strictly  one  way, option
       send_timeout comes in handy.