Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
gen_tcp(3)		   Erlang Module Definition		    gen_tcp(3)

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 con-
       nection:

       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  con-
       nection,	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} |
	   {tclass, integer() >= 0} |
	   {ttl, integer() >= 0} |
	   {recvtos, boolean()}	|
	   {recvtclass,	boolean()} |
	   {recvttl, boolean()}	|
	   {ipv6_v6only, boolean()}

       pktoptions_value() = {pktoptions, inet:ancillary_data()}

	      If the platform implements the IPv4 option IP_PKTOPTIONS,	or the
	      IPv6  option  IPV6_PKTOPTIONS  or	 IPV6_2292PKTOPTIONS  for  the
	      socket  this  value  is returned from inet:getopts/2 when	called
	      with the option name pktoptions.

	  Note:
	      This option appears to be	VERY Linux specific, and its existence
	      in  future  Linux	kernel versions	is also	worrying since the op-
	      tion is part of RFC 2292 which is	since long (2003) obsoleted by
	      RFC  3542	that explicitly	removes	this possibility to get	packet
	      information from a stream	socket.	For comparision:  it  has  ex-
	      isted in FreeBSD but is now removed, at least since FreeBSD 10.

       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 |
	   pktoptions |
	   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 |
	   tclass |
	   ttl |
	   recvtos |
	   recvtclass |
	   recvttl |
	   pktoptions |
	   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()} |
	   {netns, file:filename_all()}	|
	   {bind_to_device, binary()} |
	   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()} |
	   {netns, file:filename_all()}	|
	   {bind_to_device, binary()} |
	   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	speci-
	      fies 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(3) 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  listen-
	      ing  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,	multi-
	      ple simultaneous accept calls can	be issued from different  pro-
	      cesses,  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 be-
	      fore 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  ad-
	      dress  Address.  Argument	Address	can be a hostname or an	IP ad-
	      dress.

	      The following options are	available:

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

		{ifaddr, Address}:
		  Same	as  {ip, Address}. If the host has many	network	inter-
		  faces, 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	speci-
		  fied,	 it  is	assumed	that the fd is already bound appropri-
		  ately.

		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 de-
	      tails) 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 de-
	      livered (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 millisec-
	      onds. Defaults to	infinity.

	  Note:
	      The  default  values for options specified to connect can	be af-
	      fected by	the Kernel configuration  parameter  inet_default_con-
	      nect_options. For	details, see inet(3).

       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  identi-
	      fied by Pid is not an existing local pid,	{error,	badarg}	is re-
	      turned. {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  cor-
	      rectly  and messages may remain in the caller's mailbox. For in-
	      stance 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 num-
	      ber, 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	speci-
		  fies 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	inter-
		  faces, 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  ac-
	      cept/1,2 to accept incoming connection requests.

	  Note:
	      The  default  values  for	options	specified to listen can	be af-
	      fected by	the Kernel configuration  parameter  inet_default_lis-
	      ten_options. For details,	see inet(3).

       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 millisec-
	      onds. 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  mul-
       tiple  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 for-
       warded 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  de-
       tected:

       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	proto-
       col is strictly one way,	option send_timeout comes in handy.

Ericsson AB			  kernel 6.3			    gen_tcp(3)

NAME | DESCRIPTION | DATA TYPES | EXPORTS | EXAMPLES

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=gen_tcp&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help