Provided by: erlang-manpages_16.b.3-dfsg-1ubuntu2.2_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}
                | {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()}
                | {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
                     | 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.

                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 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()

              Immediately close a socket in one or two directions.

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

              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!