Provides access to TCP/IP protocols.
See also ERTS User's Guide, Inet configuration for more information on how to configure an Erlang runtime system for IP communication.
Two Kernel configuration parameters affect the behaviour of all
sockets opened on an Erlang node:
inet_default_connect_options
can contain a list of default
options used for all sockets returned when doing connect
,
and inet_default_listen_options
can contain a list of
default options used when issuing a listen
call. When
accept
is issued, the values of the listensocket options
are inherited, why no such application variable is needed for
accept
.
Using the Kernel configuration parameters mentioned above, one
can set default options for all TCP sockets on a node. This should
be used with care, but options like {delay_send,true}
might be specified in this way. An example of starting an Erlang
node with all sockets using delayed send could look like this:
$ erl -sname test -kernel \ inet_default_connect_options '[{delay_send,true}]' \ inet_default_listen_options '[{delay_send,true}]'
Note that the default option {active, true}
currently
cannot be changed, for internal reasons.
#hostent{h_addr_list = [ip_address()] % list of addresses for this host h_addrtype = inet | inet6 h_aliases = [hostname()] % list of aliases h_length = int() % length of address in bytes h_name = hostname() % official name for host The record is defined in the Kernel include file "inet.hrl" Add the following directive to the module: -include_lib("kernel/include/inet.hrl"). hostname() = atom() | string() ip_address() = {N1,N2,N3,N4} % IPv4 | {K1,K2,K3,K4,K5,K6,K7,K8} % IPv6 Ni = 0..255 Ki = 0..65535 posix() an atom which is named from the Posix error codes used in Unix, and in the runtime libraries of most C compilers socket() see gen_tcp(3), gen_udp(3)
Addresses as inputs to functions can be either a string or a
tuple. For instance, the IP address 150.236.20.73 can be passed to
gethostbyaddr/1
either as the string "150.236.20.73"
or as the tuple {150, 236, 20, 73}
.
IPv4 address examples:
Address ip_address() ------- ------------ 127.0.0.1 {127,0,0,1} 192.168.42.2 {192,168,42,2}
IPv6 address examples:
Address ip_address() ------- ------------ ::1 {0,0,0,0,0,0,0,1} ::192.168.42.2 {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2} FFFF::192.168.42.2 {16#FFFF,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2} 3ffe:b80:1f8d:2:204:acff:fe17:bf38 {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38} fe80::204:acff:fe17:bf38 {16#fe80,0,0,0,0,16#204,16#acff,16#fe17,16#bf38}
A function that may be useful is inet_parse:address/1
:
1> inet_parse:address("192.168.42.2"). {ok,{192,168,42,2}} 2> inet_parse:address("FFFF::192.168.42.2"). {ok,{65535,0,0,0,0,0,49320,10754}}
Types:
Socket = socket()
Closes a socket of any type.
Types:
Par, Val -- see below
Returns the state of the Inet configuration database in form of a list of recorded configuration parameters. (See the ERTS User's Guide, Inet configuration, for more information). Only parameters with other than default values are returned.
format_error(Posix) -> string()
Types:
Posix = posix()
Returns a diagnostic error string. See the section below
for possible Posix
values and the corresponding
strings.
getaddr(Host, Family) -> {ok, Address} | {error, posix()}
Types:
Host = ip_address() | string() | atom()
Family = inet | inet6
Address = ip_address()
posix() = term()
Returns the IP-address for Host
as a tuple of
integers. Host
can be an IP-address, a single hostname
or a fully qualified hostname.
getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}
Types:
Host = ip_address() | string() | atom()
Addresses = [ip_address()]
Family = inet | inet6
Returns a list of all IP-addresses for Host
.
Host
can be an IP-adress, a single hostname or a fully
qualified hostname.
gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}
Types:
Address = string() | ip_address()
Hostent = #hostent{}
Returns a hostent
record given an address.
gethostbyname(Name) -> {ok, Hostent} | {error, posix()}
Types:
Hostname = hostname()
Hostent = #hostent{}
Returns a hostent
record given a hostname.
gethostbyname(Name, Family) -> {ok, Hostent}
| {error, posix()}
Types:
Hostname = hostname()
Family = inet | inet6
Hostent = #hostent{}
Returns a hostent
record given a hostname, restricted
to the given address family.
gethostname() -> {ok, Hostname} | {error, posix()}
Types:
Hostname = string()
Returns the local hostname. Will never fail.
getopts(Socket, Options) -> OptionValues | {error, posix()}
Types:
Socket = term()
Options = [Opt | RawOptReq]
Opt = atom()
RawOptReq = {raw, Protocol, OptionNum, ValueSpec}
Protocol = int()
OptionNum = int()
ValueSpec = ValueSize | ValueBin
ValueSize = int()
ValueBin = binary()
OptionValues = [{Opt, Val} | {raw, Protocol, OptionNum,
ValueBin}]
Gets one or more options for a socket. See inet:setopts/2 for a list of available options.
The number of elements in the returned OptionValues
list does not necessarily correspond to the number of options
asked for. If the operating system fails to support an option,
it is simply left out in the returned list. An error tuple is only
returned when getting options for the socket is impossible
(i.e. the socket is closed or the buffer size in a raw request
is too large). This behavior is kept for backward
compatibility reasons.
A RawOptReq
can be used to get information about
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non portable, but
allows the Erlang programmer to take advantage of unusual features
present on the current platform.
The RawOptReq
consists of the tag raw
followed
by the protocol level, the option number and either a binary
or the size, in bytes, of the
buffer in which the option value is to be stored. A binary
should be used when the underlying getsockopt
requires
input
in the argument field, in which case the size of the binary
should correspond to the required buffer
size of the return value. The supplied values in a RawOptReq
correspond to the second, third and fourth/fifth parameters to the
getsockopt
call in the C socket API. The value stored
in the buffer is returned as a binary ValueBin
where all values are coded in the native endianess.
Asking for and inspecting raw socket options require low level information about the current operating system and TCP stack.
As an example, consider a Linux machine where the
TCP_INFO
option could be used to collect TCP statistics
for a socket. Lets say we're interested in the
tcpi_sacked
field of the struct tcp_info
filled in when asking for TCP_INFO
. To
be able to access this information, we need to know both the
numeric value of the protocol level IPPROTO_TCP
, the
numeric value of the option TCP_INFO
, the size of the
struct tcp_info
and the size and offset of
the specific field. By inspecting the headers or writing a small C
program, we found IPPROTO_TCP
to be 6,
TCP_INFO
to be 11, the structure size to be 92 (bytes),
the offset of tcpi_sacked
to be 28 bytes and the actual
value to be a 32 bit integer. We could use the following
code to retrieve the value:
get_tcpi_sacked(Sock) -> {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]), <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info, TcpiSacked.
Preferably, you would check the machine type, the OS and the kernel version prior to executing anything similar to the code above.
peername(Socket) -> {ok, {Address, Port}}
| {error, posix()}
Types:
Socket = socket()
Address = ip_address()
Port = int()
Returns the address and port for the other end of a connection.
Types:
Socket = socket()
Port = int()
Returns the local port number for a socket.
sockname(Socket) -> {ok, {Address, Port}}
| {error, posix()}
Types:
Socket = socket()
Address = ip_address()
Port = int()
Returns the local address and port number for a socket.
setopts(Socket, Options) -> ok | {error, posix()}
Types:
Socket = term()
Options = [{Opt, Val} | {raw, Protocol, Option,
ValueBin}]
Protocol = int()
OptionNum = int()
ValueBin = binary()
Opt, Val -- see below
Sets one or more options for a socket. The following options are available:
{active, true | false | once}
true
, which is the default,
everything received from the socket will be sent as
messages to the receiving process. If the value is
false
(passive mode), the process must explicitly
receive incoming data by calling gen_tcp:recv/2,3
or gen_udp:recv/2,3
(depending on the type of
socket).once
({active, once}
),
one data message from the socket will be sent
to the process. To receive one more message,
setopts/2
must be called again with the
{active, once}
option.{active, once}
, the socket changes
behaviour automatically when data is received. This can
sometimes be confusing in combination with connection
oriented sockets (i.e. gen_tcp
) as a socket with
{active, false}
behaviour reports closing
differently than a socket with {active, true}
behaviour. To make programming easier, a socket where
the peer closed and this was detected while in
{active, false}
mode, will still generate the
message
{tcp_closed,Socket}
when set to {active,
once}
or {active, true}
mode. It is therefore
safe to assume that the message
{tcp_closed,Socket}
, possibly followed by socket
port termination (depending on the exit_on_close
option) will eventually appear when a socket changes
back and forth between {active, true}
and
{active, false}
mode. However,
when peer closing is detected is all up to the
underlying TCP/IP stack and protocol.{active,true}
mode provides no flow
control; a fast sender could easily overflow the
receiver with incoming messages. Use active mode only if
your high-level protocol provides its own flow control
(for instance, acknowledging received messages) or the
amount of data exchanged is small. {active,false}
mode or use of the {active, once}
mode provides
flow control; the other side will not be able send
faster than the receiver can read.{broadcast, Boolean}
(UDP sockets)
{delay_send, Boolean}
{delay_send, true}
will make all messages queue up. This makes
the messages actually sent onto the network be larger but
fewer. The option actually affects the scheduling of send
requests versus Erlang processes instead of changing any
real property of the socket. Needless to say it is an
implementation specific option. Default is false
.
{dontroute, Boolean}
{exit_on_close, Boolean}
true
.false
is if you want
to continue sending data to the socket after a close has
been detected, for instance if the peer has used
gen_tcp:shutdown/2
to shutdown the write side.{header, Size}
binary
option was specified when the socket was created. If
the header
option is specified, the first
Size
number bytes of data received from the socket
will be elements of a list, and the rest of the data will
be a binary given as the tail of the same list. If for
example Size == 2
, the data received will match
[Byte1,Byte2|Binary]
.{keepalive, Boolean}
(TCP/IP sockets)
{nodelay, Boolean}
(TCP/IP sockets)
Boolean == true
, the TCP_NODELAY
option
is turned on for the socket, which means that even small
amounts of data will be sent immediately.{packet, PacketType}
(TCP/IP sockets)
raw | 0
1 | 2 | 4
asn1 | cdr | sunrm | fcgi | tpkt | line
gen_tcp:recv/2,3
returns one complete packet.
The header is not stripped off.asn1
- ASN.1 BER,
sunrm
- Sun's RPC encoding,
cdr
- CORBA (GIOP 1.1),
fcgi
- Fast CGI,
tpkt
- TPKT format [RFC1006],
line
- Line mode, a packet is a line
terminated with newline, lines longer than
the receive buffer are truncated.{packet_size, Integer}
(TCP/IP sockets)
{read_packets, Integer}
(UDP sockets)
{recbuf, Integer}
{reuseaddr, Boolean}
{send_timeout, Integer}
{error,timeout}
. How much of a packet that actually
got sent is unknown, why the socket should be closed
whenever a timeout has occured. Default is
infinity
.{sndbuf, Integer}
{priority, Integer}
{tos, Integer}
In addition to the options mentioned above, raw
option specifications can be used. The raw options are
specified as a tuple of arity four, beginning with the tag
raw
, followed by the protocol level, the option number
and the actual option value specified as a binary. This
corresponds to the second, third and fourth argument to the
setsockopt
call in the C socket API. The option value
needs to be coded in the native endianess of the platform and,
if a structure is required, needs to follow the struct
alignment conventions on the specific platform.
Using raw socket options require detailed knowledge about the current operating system and TCP stack.
As an example of the usage of raw options, consider a Linux
system where you want to set the TCP_LINGER2
option on
the IPPROTO_TCP
protocol level in the stack. You know
that on this particular system it defaults to 60 (seconds),
but you would like to lower it to 30 for a particular
socket. The TCP_LINGER2
option is not explicitly
supported by inet, but you know that the protocol level
translates to the number 6, the option number to the number 8
and the value is to be given as a 32 bit integer. You can use
this line of code to set the option for the socket named
Sock
:
inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),
As many options are silently discarded by the stack if they are given out of range, it could be a good idea to check that a raw option really got accepted. This code places the value in the variable TcpLinger2:
{ok,[{raw,6,8,<<TcpLinger2:32/native>>}]}=inet:getopts(Sock,[{raw,6,8,4}]),
Code such as the examples above is inherently non portable, even different versions of the same OS on the same platform may respond differently to this kind of option manipulation. Use with care.
Note that the default options for TCP/IP sockets can be changed with the Kernel configuration parameters mentioned in the beginning of this document.
e2big
- argument list too long
eacces
- permission denied
eaddrinuse
- address already in use
eaddrnotavail
- cannot assign requested address
eadv
- advertise error
eafnosupport
- address family not supported by
protocol family
eagain
- resource temporarily unavailable
ealign
- EALIGN
ealready
- operation already in progress
ebade
- bad exchange descriptor
ebadf
- bad file number
ebadfd
- file descriptor in bad state
ebadmsg
- not a data message
ebadr
- bad request descriptor
ebadrpc
- RPC structure is bad
ebadrqc
- bad request code
ebadslt
- invalid slot
ebfont
- bad font file format
ebusy
- file busy
echild
- no children
echrng
- channel number out of range
ecomm
- communication error on send
econnaborted
- software caused connection abort
econnrefused
- connection refused
econnreset
- connection reset by peer
edeadlk
- resource deadlock avoided
edeadlock
- resource deadlock avoided
edestaddrreq
- destination address required
edirty
- mounting a dirty fs w/o force
edom
- math argument out of range
edotdot
- cross mount point
edquot
- disk quota exceeded
eduppkg
- duplicate package name
eexist
- file already exists
efault
- bad address in system call argument
efbig
- file too large
ehostdown
- host is down
ehostunreach
- host is unreachable
eidrm
- identifier removed
einit
- initialization error
einprogress
- operation now in progress
eintr
- interrupted system call
einval
- invalid argument
eio
- I/O error
eisconn
- socket is already connected
eisdir
- illegal operation on a directory
eisnam
- is a named file
el2hlt
- level 2 halted
el2nsync
- level 2 not synchronized
el3hlt
- level 3 halted
el3rst
- level 3 reset
elbin
- ELBIN
elibacc
- cannot access a needed shared library
elibbad
- accessing a corrupted shared library
elibexec
- cannot exec a shared library directly
elibmax
- attempting to link in more shared
libraries than system limit
elibscn
- .lib section in a.out corrupted
elnrng
- link number out of range
eloop
- too many levels of symbolic links
emfile
- too many open files
emlink
- too many links
emsgsize
- message too long
emultihop
- multihop attempted
enametoolong
- file name too long
enavail
- not available
enet
- ENET
enetdown
- network is down
enetreset
- network dropped connection on reset
enetunreach
- network is unreachable
enfile
- file table overflow
enoano
- anode table overflow
enobufs
- no buffer space available
enocsi
- no CSI structure available
enodata
- no data available
enodev
- no such device
enoent
- no such file or directory
enoexec
- exec format error
enolck
- no locks available
enolink
- link has be severed
enomem
- not enough memory
enomsg
- no message of desired type
enonet
- machine is not on the network
enopkg
- package not installed
enoprotoopt
- bad proocol option
enospc
- no space left on device
enosr
- out of stream resources or not a stream
device
enosym
- unresolved symbol name
enosys
- function not implemented
enotblk
- block device required
enotconn
- socket is not connected
enotdir
- not a directory
enotempty
- directory not empty
enotnam
- not a named file
enotsock
- socket operation on non-socket
enotsup
- operation not supported
enotty
- inappropriate device for ioctl
enotuniq
- name not unique on network
enxio
- no such device or address
eopnotsupp
- operation not supported on socket
eperm
- not owner
epfnosupport
- protocol family not supported
epipe
- broken pipe
eproclim
- too many processes
eprocunavail
- bad procedure for program
eprogmismatch
- program version wrong
eprogunavail
- RPC program not available
eproto
- protocol error
eprotonosupport
- protocol not supported
eprototype
- protocol wrong type for socket
erange
- math result unrepresentable
erefused
- EREFUSED
eremchg
- remote address changed
eremdev
- remote device
eremote
- pathname hit remote file system
eremoteio
- remote i/o error
eremoterelease
- EREMOTERELEASE
erofs
- read-only file system
erpcmismatch
- RPC version is wrong
erremote
- object is remote
eshutdown
- cannot send after socket shutdown
esocktnosupport
- socket type not supported
espipe
- invalid seek
esrch
- no such process
esrmnt
- srmount error
estale
- stale remote file handle
esuccess
- Error 0
etime
- timer expired
etimedout
- connection timed out
etoomanyrefs
- too many references
etxtbsy
- text file or pseudo-device busy
euclean
- structure needs cleaning
eunatch
- protocol driver not attached
eusers
- too many users
eversion
- version mismatch
ewouldblock
- operation would block
exdev
- cross-domain link
exfull
- message tables full
nxdomain
- the hostname or domain name could not be
found