Provided by: erlang-manpages_18.3-dfsg-1ubuntu3.1_all bug

NAME

       gen_tcp - Interface to TCP/IP sockets

DESCRIPTION

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

       The following code fragment provides 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),
           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 the examples section.

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:ip_address()} |
           {fd, Fd :: integer() >= 0} |
           {ifaddr, inet:ip_address()} |
           inet:address_family() |
           {port, inet:port_number()} |
           {tcp_module, module()} |
           option()

       listen_option() =
           {ip, inet:ip_address()} |
           {fd, Fd :: integer() >= 0} |
           {ifaddr, inet:ip_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

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

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

              Types:

                 Address = inet:ip_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.  The
              Address argument can be either a hostname, or an IP address.

              The available options are:

                {ip, ip_address()}:
                  If  the host has several network interfaces, this option specifies which one to
                  use.

                {ifaddr, ip_address()}:
                  Same as {ip, ip_address()}. If the host has several  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,  ip_address()}  and/or  {port,
                  port_number()}  is  combined with this option the fd will be bound to the given
                  interface and port before connecting. If these options  are  not  given  it  is
                  assumed that the fd is already bound appropriately.

                inet:
                  Set up the socket for IPv4.

                inet6:
                  Set up the socket for IPv6.

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

                {tcp_module, module()}:
                  Override  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:

              {tcp_error, Socket, Reason}

              unless  {active,  false}  is  specified in the option list for the socket, in which
              case packets are retrieved by calling recv/2.

              The optional Timeout parameter specifies a timeout  in  milliseconds.  The  default
              value is infinity.

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

       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 the 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 available options are:

                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 defaults to 5. The backlog value
                  defines the maximum length that the queue of pending connections may grow to.

                {ip, ip_address()}:
                  If the host has several network interfaces, this option specifies which one  to
                  listen on.

                {port, Port}:
                  Specify 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, ip_address()}:
                  Same as {ip, ip_address()}. If the host has several  network  interfaces,  this
                  option specifies which one to use.

                inet6:
                  Set up the socket for IPv6.

                inet:
                  Set up the socket for IPv4.

                {tcp_module, module()}:
                  Override  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 can only be used in calls to accept/1,2.

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

       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 listen socket. Socket must be a socket
              returned from listen/2. Timeout specifies  a  timeout  value  in  ms,  defaults  to
              infinity.

              Returns  {ok,  Socket}  if  a  connection  is  established,  or  {error, closed} if
              ListenSocket is closed, or {error, timeout} if no connection is established  within
              the  specified  time, or {error, system_limit} if all available ports in the Erlang
              emulator are in use. May also return 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:

              {tcp, Socket, Data}

              unless {active, false} was specified in the option list for the listen  socket,  in
              which case packets are retrieved by calling recv/2.

          Note:
              It  is worth noting that 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.

       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 timeout option, you use the send_timeout  socket  option
              if timeouts are desired. See the examples section.

       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.

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

              The Length argument is only meaningful when the socket is in raw mode  and  denotes
              the  number  of  bytes to read. If Length = 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 gets closed from the other side.

              The  optional  Timeout  parameter  specifies a timeout in milliseconds. The default
              value is infinity.

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

              Types:

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

              Assigns a new controlling process Pid to Socket. The  controlling  process  is  the
              process  which  receives  messages  from the socket. If called by any other process
              than the current controlling process, {error, not_owner} is returned.

       close(Socket) -> ok

              Types:

                 Socket = socket()

              Closes a TCP socket.

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

              Types:

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

              Close 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, then the
              socket is shutdown immediately and any error encountered is returned in Reason.

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

              To  be  able  to  handle  that  the peer has done a shutdown on the write side, the
              {exit_on_close, false} option is useful.

EXAMPLES

       The following example illustrates usage of the {active,once} option and  multiple  accepts
       by implementing a server as a number of worker processes doing accept on one single listen
       socket. The start/2 function takes the number of worker processes as well as a port number
       to listen for incoming connections on. If LPort is specified as 0, an ephemeral portnumber
       is used, why the start function returns the actual portnumber 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.

       A simple client could look like this:

       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 fact that the send call does not accept a timeout option, is because timeouts on  send
       is  handled  through the socket option send_timeout. The behavior of a send operation with
       no receiver is in a very high degree defined by the underlying TCP stack, as well  as  the
       network  infrastructure.  If  one wants to write code that handles a hanging receiver that
       might eventually cause the sender to hang on  a  send  call,  one  writes  code  like  the
       following.

       Consider  a  process that receives data from a client process that is to be forwarded to a
       server on the network. The process has connected to the server via TCP/IP and does not get
       any  acknowledge  for each message it sends, but has to rely on the send timeout option to
       detect that the other end is unresponsive. We  could  use  the  send_timeout  option  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, we can now detect send timeouts:

       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  would  suffice  to detect timeouts on receive, as most protocols include some
       sort of acknowledgment from the server, but if the  protocol  is  strictly  one  way,  the
       send_timeout option comes in handy!