模块
inet
模块概述
访问TCP / IP协议。
描述
此模块提供对TCP/IP协议的访问。
另请参阅《ERTS用户指南:Inet配置》,以获取有关如何配置用于IP通信的Erlang运行时系统的更多信息。
以下两个内核配置参数会影响在Erlang节点上打开的所有套接字的行为:
- inet_default_connect_options可以包含一组默认选项,这些默认选项用于进行connect时返回的所有套接字。
- inet_default_listen_options可以包含发出listen调用时使用的默认选项的列表。
当accpet被发出,监听套接字选项的值被继承。对于accept不需要这样的应用程序变量。
使用上面的内核配置参数,可以为节点上的所有TCP套接字设置默认选项,但是请谨慎使用。可以通过这种方式指定诸如{delay_send,true}之类的选项。以下是启动Erlang节点在所有套接字上使用延迟发送的示例:
$ erl -sname test -kernel \
inet_default_connect_options ‘[{delay_send,true}]‘ \
inet_default_listen_options ‘[{delay_send,true}]‘
请注意 ,由于内部原因,无法更改默认选项{active,true}。
作为函数输入的地址可以是字符串或元组。例如,可以将IP地址150.236.20.73 作为字符串“ 150.236.20.73” 或作为元组{150,236,20,73 }传递给 gethostbyaddr/1。
IPv4地址示例:
Address ip_address()
------- ------------
127.0.0.1 {127,0,0,1}
192.168.42.2 {192,168,42,2}
IPv6地址示例:
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 {0,0,0,0,0,16#FFFF,(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}
函数 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,{0,0,0,0,0,65535,49320,10754}}
数据类型
hostent() =
#hostent{h_name = inet:hostname(),
h_aliases = [inet:hostname()],
h_addrtype = inet | inet6,
h_length = integer() >= 0,
h_addr_list = [inet:ip_address()]}
该记录在内核包含文件 “inet.hrl”中定义。
将以下指令添加到模块:
-include_lib("kernel/include/inet.hrl").
hostname() = atom() | string()
ip_address() = ip4_address() | ip6_address()
ip4_address() = {0..255, 0..255, 0..255, 0..255}
ip6_address() =
{0..65535,
0..65535,
0..65535,
0..65535,
0..65535,
0..65535,
0..65535,
0..65535}
port_number() = 0..65535
local_address() = {local, File :: binary() | string()}
该地址族仅适用于类Unix系统。
文件通常是本地文件系统中的文件路径名。传统上,它的长度受操作系统的限制,为108个字节。
将binary()原样传递给操作系统,但是根据系统文件名编码模式对string()进行编码。
其他地址也是可能的,例如Linux实现“抽象地址”。请参见系统部分中有关Unix域套接字的文档,通常是unix,请参见手册第7节。
在可以使用此地址族的大多数API函数中,端口号必须为0。
socket_address() =
ip_address() | any | loopback | local_address()
socket_getopt() =
gen_sctp:option_name() |
gen_tcp:option_name() |
gen_udp:option_name()
socket_setopt() =
gen_sctp:option() | gen_tcp:option() | gen_udp:option()
returned_non_ip_address() =
{local, binary()} | {unspec, <<>>} | {undefined, any()}
从套接字API函数返回的,除ip_address()之外的地址。特别参见local_address()。该UNSPEC家族对应AF_UNSPEC,如果对方没有套接字地址可能发生。
undefined家族仅发生在不大可能发生的事件,一个虚拟机不能识别的地址家族。
posix() =
eaddrinuse |
eaddrnotavail |
eafnosupport |
ealready |
econnaborted |
econnrefused |
econnreset |
edestaddrreq |
ehostdown |
ehostunreach |
einprogress |
eisconn |
emsgsize |
enetdown |
enetunreach |
enopkg |
enoprotoopt |
enotconn |
enotty |
enotsock |
eproto |
eprotonosupport |
eprototype |
esocktnosupport |
etimedout |
ewouldblock |
exbadport |
exbadseq |
file:posix()
从Unix中使用的POSIX错误代码和大多数C编译器的运行时库中命名的原子。请参阅POSIX错误代码部分。
socket()
参见 gen_tcp:type-socket 和 gen_udp:type-socket。
address_family() = inet | inet6 | local
socket_protocol() = tcp | udp | sctp
导出
close(Socket) -> ok
Types
Socket = socket()
关闭任何类型的套接字。
format_error(Reason) -> string()
Types
Reason = posix() | system_limit
返回诊断错误字符串。 有关可能的POSIX值和相应的字符串,请参阅POSIX错误代码部分。
get_rc() ->
[{Par :: atom(), Val :: any()} |
{Par :: atom(), Val1 :: any(), Val2 :: any()}]
以记录的配置参数列表的形式返回Inet配置数据库的状态。 有关更多信息,请参见《ERTS用户指南:Inet配置》。
仅返回具有默认值以外的实际参数,例如,不会返回为配置参数指定其他来源的指令,也不会返回清除参数的指令。
getaddr(Host, Family) -> {ok, Address} | {error, posix()}
Types
Host = ip_address() | hostname()
Family = address_family()
Address = ip_address()
以整数元组格式返回Host的IP地址。 主机可以是IP地址,单个主机名或标准主机名。
getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}
Types
Host = ip_address() | hostname()
Family = address_family()
Addresses = [ip_address()]
返回主机的所有IP地址的列表。 主机可以是IP地址,单个主机名或标准主机名。
gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}
Types
Address = string() | ip_address()
Hostent = hostent()
返回具有指定地址的主机的主机记录。
gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()}
Types
Hostname = hostname()
Hostent = hostent()
返回具有指定主机名的主机的主机记录。
如果解析器选项inet6为true,则查找IPv6地址。
gethostbyname(Hostname, Family) ->
{ok, Hostent} | {error, posix()}
Types
Hostname = hostname()
Family = address_family()
Hostent = hostent()
返回具有指定名称的主机的主机记录,仅限于指定的地址族。
gethostname() -> {ok, Hostname}
Types
Hostname = string()
返回本地主机名。 从未失败。
getifaddrs() -> {ok, Iflist} | {error, posix()}
Types
Iflist = [{Ifname, [Ifopt]}]
Ifname = string()
Ifopt =
{flags, [Flag]} |
{addr, Addr} |
{netmask, Netmask} |
{broadaddr, Broadaddr} |
{dstaddr, Dstaddr} |
{hwaddr, Hwaddr}
Flag = up | broadcast | loopback | pointtopoint | running | multicast
Addr = Netmask = Broadaddr = Dstaddr = ip_address()
Hwaddr = [byte()]
返回一个包含接口名称和接口地址的2元组列表。 Ifname是Unicode字符串。 Hwaddr取决于硬件,例如,在以太网接口上,它是6字节的以太网地址(MAC地址(EUI-48地址))。
如果接口具有多个地址,则在结果列表中重复元组{addr,Addr},{netmask,_}和{broadaddr__}。如果遇到带有多个{flag,_}或{hwaddr,_}元组的接口,那么您的接口可能很奇怪,或者此功能可能有错误。元组{flag,_}是必需的,所有其他都是可选的。
不要过分依赖Flag原子或Ifopt元组的顺序。但是,有一些规则:
- {addr,_}之后紧跟{netmask,_}。
- 如果未设置标志广播且设置了标志点对点,则紧随其后跟随{broadaddr,_}。
- 在{addr,_}元组之后的任何{netmask,_},{broadaddr,_}或{dstaddr,_}元组都与该地址有关。
在Solaris上不返回元组{hwaddr,_},因为硬件地址在历史上属于链接层,并且只有超级用户才能读取此类地址。
警告:在Windows上,数据是从不同的OS API函数获取的,因此可以像一些Flag值一样计算Netmask和Broadaddr值。 报告恶意错误。
getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}
Types
Socket = socket()
Options = [socket_getopt()]
OptionValues = [socket_setopt()]
获取套接字的一个或多个选项。有关可用选项的列表,请参见setopts/2。
返回的OptionValues列表中的元素数量不一定与所要求的选项数量相对应。如果操作系统不支持某个选项,则会在返回的列表中将其忽略。仅当无法获取套接字选项时(即套接字已关闭或原始请求中的缓冲区大小太大),才返回错误元组。出于向后兼容的原因保留此行为。
原始选项请求RawOptReq = {raw,Protocol,OptionNum,ValueSpec}可用于获取有关仿真器不(明确)支持的套接字选项的信息。使用原始套接字选项使代码不可移植,但允许Erlang程序员利用当前平台上存在的异常功能。
RawOptReq由标签raw组成,其后是协议级别,选项号以及二进制或大小(以字节为单位)的缓冲区,用于存储选项值。当基础的getsockopt需要在参数字段中输入时,将使用二进制。在这种情况下,二进制大小应对应于所需的返回值缓冲区大小。 RawOptReq中提供的值与C套接字API中的getsockopt调用的第二,第三和第四/第五个参数相对应。存储在缓冲区中的值以二进制ValueBin的形式返回,其中所有值均以本机字节序编码。
询问和检查原始套接字选项需要有关当前操作系统和TCP堆栈的低级信息。
例子:
考虑一个Linux计算机,其中可以使用选项TCP_INFO来收集套接字的TCP统计信息。 假设您对请求TCP_INFO时填写的struct tcp_info的字段tcpi_sacked感兴趣。 为了能够访问此信息,您需要了解以下内容:
- 协议级别IPPROTO_TCP的数值
- 选项TCP_INFO的数值
- struct tcp_info的大小
- 特定字段的大小和偏移量
通过检查头文件或编写小型C程序,可以发现IPPROTO_TCP为6,TCP_INFO为11,结构大小为92(字节),tcpi_sacked的偏移量为28字节,并且值为32位整数。 以下代码可用于检索值:
get_tcpi_sacked(Sock) ->
{ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),
<<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,
TcpiSacked.
最好在执行类似于此代码的操作之前,先检查机器类型,操作系统和内核版本。
getstat(Socket) -> {ok, OptionValues} | {error, posix()}
getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()}
Types
Socket = socket()
Options = [stat_option()]
OptionValues = [{stat_option(), integer()}]
stat_option() =
recv_cnt |
recv_max |
recv_avg |
recv_oct |
recv_dvi |
send_cnt |
send_max |
send_avg |
send_oct |
send_pend
获取套接字的一个或多个统计选项。
getstat(Socket)等效于getstat(Socket,[recv_avg,recv_cnt,recv_dvi,recv_max,recv_oct,send_avg,send_cnt,send_dvi,send_max,send_oct])。
提供以下选项:
recv_avg
套接字接收的平均数据包大小(以字节为单位)。
recv_cnt
套接字接收的包数。
recv_dvi
套接字收到的平均数据包大小偏差(以字节为单位)。
recv_max
套接字接收的最大数据包的大小(以字节为单位)。
recv_oct
套接字接收的字节数。
send_avg
从套接字发送的数据包的平均大小(以字节为单位)。
send_cnt
从套接字发送的数据包数。
send_dvi
从套接字发送的平均数据包大小偏差(以字节为单位)。
send_max
从套接字发送的最大数据包的大小(以字节为单位)。
send_oct
从套接字发送的字节数。
i() -> ok
i(Proto :: socket_protocol()) -> ok
i(X1 :: socket_protocol(), Fs :: [atom()]) -> ok
列出所有TCP,UDP和SCTP套接字,包括Erlang运行时系统使用的套接字以及应用程序创建的套接字。
提供以下选项:
port
端口的内部索引。
module
套接字的回调模块。
recv
套接字接收的字节数。
sent
从套接字发送的字节数。
owner
套接字所有者进程。
local_address
套接字的本地地址。
foreign_address
连接另一端的地址和端口。
state
连接状态。
type
STREAM或DGRAM或SEQPACKET。
ntoa(IpAddress) -> Address | {error, einval}
Types
Address = string()
IpAddress = ip_address()
解析ip_address() 并返回IPv4或IPv6地址字符串。
parse_address(Address) -> {ok, IPAddress} | {error, einval}
Types
Address = string()
IPAddress = ip_address()
解析IPv4或IPv6地址字符串,并返回ip4_address()或ip6_address()。 接受缩短的IPv4地址字符串。
parse_ipv4_address(Address) -> {ok, IPv4Address} | {error, einval}
Types
Address = string()
IPv4Address = ip_address()
解析IPv4地址字符串并返回ip4_address()。 接受缩短的IPv4地址字符串。
parse_ipv4strict_address(Address) ->
{ok, IPv4Address} | {error, einval}
Types
Address = string()
IPv4Address = ip_address()
解析包含四个字段(未缩短)的IPv4地址字符串,并返回ip4_address()。
parse_ipv6_address(Address) -> {ok, IPv6Address} | {error, einval}
Types
Address = string()
IPv6Address = ip_address()
解析IPv6地址字符串并返回ip6_address()。 如果指定了IPv4地址字符串,则返回IPv4映射的IPv6地址。
parse_ipv6strict_address(Address) ->
{ok, IPv6Address} | {error, einval}
Types
Address = string()
IPv6Address = ip_address()
解析IPv6地址字符串并返回ip6_address()。 不接受IPv4地址。
ipv4_mapped_ipv6_address(X1 :: ip_address()) -> ip_address()
将IPv4地址转换为映射了IPv4的IPv6地址或反向。 从IPv6地址转换时,除了2个低位字以外的所有其他字符都将被忽略,因此此功能还可以用于IPv4映射的其他类型的地址。
parse_strict_address(Address) -> {ok, IPAddress} | {error, einval}
Types
Address = string()
IPAddress = ip_address()
解析IPv4或IPv6地址字符串,并返回ip4_address()或ip6_address()。 不接受缩短的IPv4地址字符串。
peername(Socket :: socket()) ->
{ok,
{ip_address(), port_number()} |
returned_non_ip_address()} |
{error, posix()}
返回连接另一端的地址和端口。
请注意,对于SCTP套接字,此函数仅返回套接字的对等地址之一。 函数peernames/1,2返回全部。
peernames(Socket :: socket()) ->
{ok,
[{ip_address(), port_number()} |
returned_non_ip_address()]} |
{error, posix()}
等效于peernames(Socket, 0).
请注意,SCTP一对多样式套接字的此功能的行为未由SCTP套接字API扩展定义。
peernames(Socket, Assoc) ->
{ok, [{Address, Port}]} | {error, posix()}
Types
Socket = socket()
Assoc = #sctp_assoc_change{} | gen_sctp:assoc_id()
Address = ip_address()
Port = integer() >= 0
返回套接字关联Assoc的另一端的所有地址/端口号对的列表。
此函数可以为多宿主套接字(例如SCTP套接字)返回多个地址。 对于其他套接字,它返回一个元素列表。
请注意,参数Assoc是由SCTP套接字API扩展定义的,对于一对一样式的套接字将被忽略。 不幸的是,特殊值0表示什么,因此它对于一对多样式套接字的行为是不确定的。
port(Socket) -> {ok, Port} | {error, any()}
Types
Socket = socket()
Port = port_number()
返回套接字的本地端口号。
setopts(Socket, Options) -> ok | {error, posix()}
Types
Socket = socket()
Options = [socket_setopt()]
为套接字设置一个或多个选项。
提供以下选项:
{active, true | false | once | N}
如果值为true(这是默认值),则将从套接字接收的所有内容作为消息发送到接收进程。
如果该值为false(被动模式),则该进程必须通过调用gen_tcp:recv/2,3,gen_udp:recv/2,3或gen_sctp:recv/1,2来显式接收传入的数据(取决于套接字的类型) 。
如果该值为once({active,once}),则套接字中的一条数据消息将发送到该进程。要再接收一条消息,必须使用选项{active,once}再次调用setopts/2。
如果该值是-32768到32767(含)之间的整数N,则将该值添加到套接字发送给控制进程的数据消息的计数中。套接字的默认消息计数为0。如果指定了负值,并且其大小等于或大于套接字的当前消息计数,则套接字的消息计数将设置为0。一旦套接字的消息计数达到0,则可能是由于向进程发送接收到的数据消息或通过显式设置该消息,然后通过特定于套接字类型的特殊消息通知该进程套接字已进入被动模式。一旦套接字进入被动模式,为了再次接收消息,必须再次调用setopts/2才能将套接字设置回主动模式。
使用{active,once}或{active,N}时,套接字在接收到数据时会自动更改行为。与面向连接的套接字(即gen_tcp)结合使用时,这可能会造成混淆,因为具有{active,false}行为的套接字报告的关闭方式与具有{active,true}行为的套接字的关闭方式不同。为了简化编程,设置为{active,once},{active,true}或{active, N}模式时,对等体关闭的套接字(在{active,false}模式下被检测到)仍会生成消息{tcp_closed,Socket}。因此可以安全地假设,当套接字在{active,true}和{active,false}模式之间来回切换时,最终会出现消息{tcp_closed,Socket},并可能随后出现套接字端口终止(取决于选项exit_on_close)。但是,当检测到对等关闭时,完全取决于基础的TCP/IP堆栈和协议。
注意{active,true}模式不提供流量控制;快速的发送者可以轻松地使接收者的消息溢出接收者。对于{active,N}模式,消息数大于零时也是如此。
仅当高级协议提供自己的流控制(例如,确认收到的消息)或交换的数据量很少时,才使用活动模式。 {active,false}模式,使用{active,once}模式或{active,N}模式(具有适用于应用程序的N值)可提供流控制。另一端发送的速度不能超过接收器可以读取的速度。
{broadcast, Boolean} (UDP sockets)
启用/禁用发送广播的权限。
{buffer, Size}
驱动程序使用的用户级软件缓冲区的大小。 不要与sndbuf和recbuf选项混淆,它们与内核套接字缓冲区相对应。 建议使val(buffer)>= max(val(sndbuf),val(recbuf))以避免不必要的复制而导致性能问题。 设置值sndbuf或recbuf时,val(buffer)会自动设置为上述最大值。 但是,由于为sndbuf和recbuf设置的大小通常会变大,因此建议您使用getopts/2来分析操作系统的行为。
请注意,这也是从单个recv调用可以接收的最大数据量。 如果您使用的MTU高于正常值,请考虑将缓冲区设置为更高。
{delay_send, Boolean}
通常,当Erlang进程发送到套接字时,驱动程序会尝试立即发送数据。 如果失败,驱动程序将使用任何可用的方法将要发送的消息排队,只要操作系统说它可以处理它。 设置{delay_send,true}会使所有消息排队。 这样,发送到网络的消息就更大,但更少。 该选项将影响发送请求与Erlang进程的调度,而不是更改套接字的任何实际属性。 该选项是特定于实现的。 默认为false。
{deliver, port | term}
当{active,true}时,数据通过以下端口传送:{S,{data,[H1,.. Hsz | Data]}}或术语:{tcp,S,[H1..Hsz | Data]}。
{dontroute, Boolean}
启用/禁用传出消息的路由旁路。
{exit_on_close, Boolean}
默认情况下,此选项设置为true。
将其设置为false的唯一原因是,如果要在检测到关闭后继续向套接字发送数据,例如,如果对等方使用gen_tcp:shutdown/2关闭写端。
{header, Size}
仅当创建套接字时指定了选项二进制时,此选项才有意义。 如果指定了选项标头,则从套接字接收的数据的第Size个数量的字节是列表的元素,其余数据是指定为同一列表尾部的二进制。 例如,如果Size == 2,则接收到的数据匹配[Byte1,Byte2 | Binary]。
{high_msgq_watermark, Size}
当消息队列上的数据量达到此限制时,套接字消息队列将设置为繁忙状态。 请注意,此限制仅涉及尚未达到ERTS内部套接字实现的数据。 默认为8 kB。
如果套接字消息队列繁忙或套接字本身繁忙,则将暂停向套接字发送数据。
有关更多信息,请参见选项low_msgq_watermark,high_watermark和low_watermark。
请注意,分发套接字禁用了high_msgq_watermark和low_msgq_watermark的使用。 使用分配缓冲区繁忙限制,这是一个类似功能。
{high_watermark, Size} (TCP/IP sockets)
当ERTS套接字实现在内部排队的数据量达到此限制时,将套接字设置为繁忙状态。 默认为8 kB。
如果套接字消息队列繁忙或套接字本身繁忙,则将暂停向套接字发送数据。
有关更多信息,请参见选项low_watermark,high_msgq_watermark和low_msqg_watermark。
{ipv6_v6only, Boolean}
限制套接字仅使用IPv6,禁止任何IPv4连接。这仅适用于IPv6套接字(选项inet6)。
在大多数平台上,必须先在套接字上设置此选项,然后才能将其与地址关联。因此,仅在创建套接字时指定它,而在调用包含此描述的函数(setopts/2)时不使用它是合理的。
将此选项设置为true的套接字的行为是唯一可移植的行为。现在,FreeBSD不建议使用IPv6的初衷是将IPv6用于所有流量(您可以使用{ipv6_v6only,false}来覆盖建议的系统默认值),但OpenBSD(受支持的GENERIC内核)禁止使用,并且在Windows(具有单独的IPv4和IPv6协议栈)。大多数Linux发行版的系统默认值仍为false。逐渐改变了操作系统之间从IPv4流量分离IPv6流量的策略,因为逐渐证明,要确保正确,安全地实现双堆栈实现是困难而复杂的。
在某些平台上,此选项唯一允许的值为true,例如OpenBSD和Windows。在这种情况下,尝试在创建套接字时将此选项设置为false会失败。
在不存在的平台上设置此选项将被忽略。使用getopts/2获取此选项不会返回任何值,即返回的列表不包含{ipv6_v6only,_}元组。在Windows上,该选项不存在,但会将其模拟为值为true的只读选项。
因此,在创建套接字时将此选项设置为true永远不会失败,除非可能是在您已将内核自定义为仅允许false的平台上进行,例如,在OpenBSD上可以这样做(但很尴尬)。
如果使用getopts/2读回选项值,但未获取任何值,则该选项在主机操作系统中不存在。 IPv6和IPv4套接字在同一端口上侦听的行为以及获取IPv4流量的IPv6套接字的行为不再可预测。
{keepalive, Boolean}(TCP/IP sockets)
默认值为false。设置为true能对一些异常断线的情况进行检测和释放,值得需要注意的是,这个与系统的tcp_keep_alive_time相关。需要将tcp_keep_alive_time设置到一个合理的值。
{linger, {true|false, Seconds}}
确定在close/1套接字调用中刷新未发送数据的超时(以秒为单位)。 如果值元组的第一个组件为false,则忽略第二个组件。 这意味着close/1立即返回,而不等待数据被刷新。 否则,第二个组件是冲洗超时(以秒为单位)。
{low_msgq_watermark, Size}
如果套接字消息队列处于繁忙状态,则当消息队列中排队的数据量低于此限制时,套接字消息队列将设置为不繁忙状态。 请注意,此限制仅涉及尚未达到ERTS内部套接字实现的数据。 默认为4 kB。
当套接字消息队列和套接字不繁忙时,将恢复由于繁忙的消息队列或繁忙的套接字而挂起的发送者。
有关更多信息,请参见选项high_msgq_watermark,high_watermark和low_watermark。
请注意,分发套接字禁用了high_msgq_watermark和low_msgq_watermark的使用。 使用分配缓冲区繁忙限制,这是一个类似功能。
{low_watermark, Size} (TCP/IP sockets)
如果套接字处于繁忙状态,则当ERTS套接字实现在内部排队的数据量低于此限制时,会将套接字设置为不繁忙状态。 默认为4 kB。
当套接字消息队列和套接字不繁忙时,将恢复由于繁忙的消息队列或繁忙的套接字而挂起的发送者。
有关更多信息,请参见选项high_watermark,high_msgq_watermark和low_msgq_watermark。
{mode, Mode :: binary | list}
接收到的数据包按照模式定义进行传递。
{netns, Namespace :: file:filename_all()}
设置套接字的网络名称空间。 参数名称空间是定义名称空间的文件名,例如“ /var/run/netns/example”,通常由命令ip netns add example创建。 必须在创建套接字的函数调用中使用此选项,即gen_tcp:connect/3,4,gen_tcp:listen/2,gen_udp:open/1,2或gen_sctp:open/0,1,2。
此选项使用特定于Linux的syscall setns()(例如在Linux内核3.0或更高版本中),因此仅在针对此类操作系统编译运行时系统时才存在。
根据setns(2)的文档,虚拟机还需要提升的特权,该特权可以以超级用户身份运行,或者(对于Linux)以CAP_SYS_ADMIN能力运行。 但是,在测试过程中,CAP_SYS_PTRACE和CAP_DAC_READ_SEARCH也被证明是必需的。
例子:
setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp
请注意,包含虚拟机可执行文件(在示例中为beam.smp)的文件系统必须是本地的,安装时不带标志nosetuid,支持扩展属性,并且内核必须支持文件功能。 至少在Ubuntu 12.04 LTS上,所有这些都是开箱即用的,除了SCTP套接字似乎不支持网络名称空间。
命名空间是一个文件名,并且按照模块文件中的讨论进行编码和解码,但以下情况除外:
- 模拟器标志+ fnu被忽略。
- 如果无法解码存储的文件名,则此选项的getopts/2返回文件名的二进制。 仅当您使用无法使用仿真器的文件名编码解码的二进制设置该选项时,才会发生这种情况:file:native_name_encoding/0。
{bind_to_device, Ifname :: binary()}
将套接字绑定到特定的网络接口。 必须在创建套接字的函数调用中使用此选项,即gen_tcp:connect/3,4,gen_tcp:listen/2,gen_udp:open/1,2或gen_sctp:open/0,1,2。
与getifaddrs/0不同,Ifname编码为二进制。 如果系统在网络设备名称中使用非7位ASCII字符(这种情况不太可能发生),则在对该参数进行编码时必须格外小心。
该选项使用特定于Linux的套接字选项SO_BINDTODEVICE,例如在Linux内核2.0.30或更高版本中,因此仅在针对此类操作系统编译运行时系统时才存在。
在Linux 3.8之前,可以设置此套接字选项,但无法使用getopts/2进行检索。 从Linux 3.8开始,它是可读的。
虚拟机还需要提升的特权,这些特权可以以超级用户身份运行,或者(对于Linux)具有CAP_NET_RAW能力。
此选项的主要用例是将套接字绑定到Linux VRF实例。
list
收到的数据包以列表形式发送。
binary
接收到的数据包以二进制形式发送。
{nodelay, Boolean}(TCP/IP sockets)
如果Boolean == true,则为套接字打开选项TCP_NODELAY,这意味着也会立即发送少量数据。
即便少量数据也立即发送。视应用场景而定,一般对于游戏这种类型的应用而言,设置为true。
{packet, PacketType}(TCP/IP sockets)
定义用于套接字的数据包类型。可能的值:
raw| 0
没有封包。
1 | 2 | 4
数据包包含一个标头,该标头指定了数据包中的字节数,然后是该字节数。标头长度可以是1个,2个或4个字节,并包含按big-endian字节顺序排列的无符号整数。每个发送操作都会生成标头,并且在每个接收操作上都会剥离标头。
4字节的标头限制为2Gb。
asn1 | cdr | sunrm | fcgi | tpkt | line
这些数据包类型仅对接收有效。发送数据包时,应用程序有责任提供正确的标头。但是,在接收时,对于接收到的每个完整数据包,将一条消息发送到控制过程,并且类似地,对gen_tcp:recv/2,3的每次调用都返回一个完整数据包。标头未剥离。
数据包类型的含义如下:
- asn1-ASN.1 BER
- sunrm-Sun的RPC编码
- CDR-CORBA(GIOP 1.1)
- fcgi-快速CGI
- tpkt-TPKT格式[RFC1006]
- line-行模式,数据包以换行符结尾的行,比接收缓冲区长的行被截断
http | http_bin
超文本传输协议。按照ERTS的erlang:decode_packet/3中描述的HttpPacket格式返回数据包。被动模式下的套接字从gen_tcp:recv返回{ok,HttpPacket},而主动套接字发送诸如{http,Socket,HttpPacket}之类的消息。
httph | httph_bin
通常不需要这两种类型,因为在读取第一行之后,套接字会在内部自动从http/http_bin切换到httph/httph_bin。但是,有时可能会有用,例如从分块编码中解析预告片。
{packet_size, Integer}(TCP/IP sockets)
设置数据包主体的最大允许长度。 如果数据包头指示数据包的长度大于最大允许长度,则该数据包被视为无效。 如果数据包头对于套接字接收缓冲区太大,则会发生相同的情况。
对于面向行的协议(line,http *),选项packet_size还可以保证接受指定长度的行,并且由于内部缓冲区的限制,该行不会被视为无效。
{line_delimiter, Char}(TCP/IP sockets)
为面向行的协议(行)设置行定界字符。 默认为$ \ n。
{raw, Protocol, OptionNum, ValueBin}
见下文。
{read_packets, Integer}(UDP sockets)
设置在数据可用时无需套接字干预即可读取的最大UDP数据包数。 当读取了这么多数据包并将其传送到目标进程后,新的数据包才被读取,直到有可用数据的新通知到达为止。 默认值是5。如果将此参数设置得太高,由于UDP数据包泛洪,系统可能会变得无响应。
{recbuf, Size}
用于套接字的接收缓冲区的最小大小。 建议您使用getopts/2来检索操作系统设置的大小。
{reuseaddr, Boolean}
允许或禁止端口号的本地重用。 默认情况下,不允许重用。
{send_timeout, Integer}
仅允许用于面向连接的套接字。
指定最长时间等待基础TCP堆栈接受发送操作。 当超过限制时,发送操作将返回{error,timeout}。 未知发送了多少数据包; 因此,只要发生超时,套接字就将关闭(请参见下面的send_timeout_close)。 默认为无穷大。
{send_timeout_close, Boolean}
仅允许用于面向连接的套接字。
与send_timeout一起使用,以指定当send操作返回{error,timeout}时是否自动关闭套接字。 推荐的设置为true,它将自动关闭套接字。 由于向后兼容,默认为false。
{show_econnreset, Boolean}(TCP/IP sockets)
当此选项设置为false时(默认情况下),将从TCP对等方收到的RST视为正常关闭(就像已发送FIN)。 gen_tcp:recv/2的调用者获得{error, closed}。 在活动模式下,控制进程收到{tcp_closed,Socket}消息,指示对等方已关闭连接。
将此选项设置为true可以区分正常关闭的连接和TCP对等端中止(有意或无意)的连接。 调用gen_tcp:recv/2会返回{error,econnreset}。 在活动模式下,控制过程会在通常的{tcp_closed,Socket}之前收到{tcp_error,Socket,econnreset}消息,就像其他任何套接字错误一样。 当检测到TCP对等体已发送RST时,对gen_tcp:send/2的调用也返回{error,econnreset}。
从gen_tcp:accept/1返回的已连接套接字从侦听套接字继承了show_econnreset设置。
{sndbuf, Size}
用于套接字的发送缓冲区的最小大小。 建议您使用getopts/2来检索操作系统设置的大小。
{priority, Integer}
在实现它的平台上设置SO_PRIORITY套接字级别选项。 行为和允许范围在不同系统之间有所不同。 该选项在未实现的平台上被忽略。 请谨慎使用。
{tos, Integer}
设置IP_TOS参数,这个参数代表了IP包的优先级和QoS选项。和系统的设置有关联。
{tclass, Integer}
在实现它的平台上设置IPV6_TCLASS IP级别选项。 行为和允许范围在不同系统之间有所不同。 该选项在未实现的平台上被忽略。 请谨慎使用。
除了这些选项之外,还可以使用原始选项规范。 原始选项被指定为三元组的元组,以标记raw开头,然后是协议级别,选项号和指定为二进制的选项值。 这对应于C套接字API中setockopt调用的第二,第三和第四个参数。 选项值必须以平台的本地字节序编码,并且,如果需要结构,则必须遵循特定平台上的结构对齐约定。
使用原始套接字选项需要有关当前操作系统和TCP堆栈的详细知识。
例子:
示例涉及原始选项的使用。 考虑一个Linux系统,您要在堆栈中的协议级别IPPROTO_TCP上设置选项TCP_LINGER2。 您知道在该特定系统上,它的默认值为60(秒),但是对于特定的套接字,您希望将其降低到30。 inet没有显式支持选项TCP_LINGER2,但是您知道协议级别将转换为数字6,将选项号转换为数字8,并将该值指定为32位整数。 您可以使用以下代码行为名为Sock的套接字设置选项:
inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}])
如果指定的选项超出范围,则许多选项将被堆栈静默丢弃; 最好检查原始选项是否被接受。 以下代码将值放在变量TcpLinger2中:
{ok,[{raw,6,8,<<TcpLinger2:32/native>>}]}=inet:getopts(Sock,[{raw,6,8,4}]),
这些示例之类的代码本质上是不可移植的,即使同一平台上同一OS的不同版本也可以对这种选项操作做出不同的响应。 小心使用。
请注意,可以使用本手册页开头提到的内核配置参数来更改TCP/IP套接字的默认选项。
sockname(Socket :: socket()) ->
{ok,
{ip_address(), port_number()} |
returned_non_ip_address()} |
{error, posix()}
返回套接字的本地地址和端口号。
请注意,对于SCTP套接字,此函数仅返回套接字地址之一。 函数socknames/1,2返回全部。
socknames(Socket :: socket()) ->
{ok,
[{ip_address(), port_number()} |
returned_non_ip_address()]} |
{error, posix()}
等同于 socknames(Socket, 0)。
socknames(Socket, Assoc) ->
{ok, [{Address, Port}]} | {error, posix()}
Types
Socket = socket()
Assoc = #sctp_assoc_change{} | gen_sctp:assoc_id()
Address = ip_address()
Port = integer() >= 0
返回指定关联Assoc的套接字的所有本地地址/端口号对的列表。
此函数可以为多宿主套接字(例如SCTP套接字)返回多个地址。 对于其他套接字,它返回一个元素列表。
请注意,参数Assoc是由SCTP套接字API扩展定义的,对于一对一样式的套接字将被忽略。 对于一对多样式的套接字,将特殊值0定义为意味着返回的地址必须没有任何特定的关联。 不同的SCTP实现方式对此的解释有些不同。
POSIX错误代码
e2big-参数列表过长
eacces-权限被拒绝
eaddrinuse-地址已在使用中
eaddrnotavail-无法分配请求的地址
eadv-广告错误
eafnosupport-协议族不支持的地址族
eagain-资源暂时不可用
ealign-EALIGN
ealready-操作正在进行中
ebade-错误的交换描述符
ebadf-错误的文件编号
ebadfd-处于不良状态的文件描述符
ebadmsg-不是数据信息
ebadr-错误的请求描述符
ebadrpc-错误的RPC结构
ebadrqc-错误的请求代码
ebadslt-无效的广告位
ebfont-错误的字体文件格式
ebusy-文件繁忙
echild-没有孩子
echrng-频道编号超出范围
ecomm-发送时发生通信错误
econnaborted-软件导致连接中止
econnrefused-连接被拒绝
econnreset-通过对等方重置连接
edeadlk-避免资源死锁
edeadlock-避免资源死锁
edestaddrreq-必需的目标地址
edirty-不用力安装脏的fs
edom-数学参数超出范围
edotdot-交叉安装点
edquot-超出磁盘配额
eduppkg-重复的软件包名称
eexist-文件已存在
efault-系统调用参数中的错误地址
efbig-文件太大
ehostdown-主机已关闭
ehostunreach-主机无法访问
eidrm-标识符已删除
einit-初始化错误
einprogress-操作正在进行中
eintr-中断的系统调用
einval-无效的参数
eio-I / O错误
eisconn-套接字已连接
eisdir-对目录的非法操作
eisnam-是命名文件
el2hlt-2级停止
el2nsync-2级未同步
el3hlt-3级停止
el3rst-3级重置
elbin-ELBIN
elibacc-无法访问所需的共享库
elibbad-访问损坏的共享库
elibexec-无法直接执行共享库
elibmax-尝试链接比系统限制更多的共享库
elibscn-a.out中的.lib节已损坏
elnrng-链接数超出范围
eloop-太多级别的符号链接
emfile-打开的文件太多
emlink-链接太多
emsgsize-消息过长
emultihop-尝试多跳
enametoolong-文件名太长
enavail-不可用
enet-ENET
enetdown-网络已关闭
enetreset-重置时网络断开连接
enetunreach-网络无法访问
enfile-文件表溢出
enoano-阳极表溢出
enobufs-没有可用的缓冲区空间
enocsi-没有可用的CSI结构
enodata-无可用数据
enodev-没有这样的设备
enoent-没有这样的文件或目录
enoexec-执行格式错误
enolck-无锁
enolink-链接已被切断
enomem-没有足够的内存
enomsg-没有所需类型的消息
enonet-机器不在网络上
enopkg-未安装软件包
enoprotoopt-错误的协议选项
enospc-设备上没有剩余空间
enosr-流资源不足或没有流设备
enosym-未解析的符号名称
enosys-功能未实现
enotblk-需要块设备
enotconn-套接字未连接
enotdir-不是目录
enotempty-目录不为空
enotnam-不是命名文件
enotsock-非套接字上的套接字操作
enotsup-不支持操作
enotty-不适合ioctl的设备
enotuniq-名称在网络上不唯一
enxio-没有这样的设备或地址
eopnotsupp-套接字不支持该操作
eperm-不是所有者
epfnosupport-不支持协议族
epipe-断管
eproclim-流程太多
eprocunavail-程序错误的程序
eprogmismatch-程序版本错误
eprogunavail-RPC程序不可用
eproto-协议错误
eprotonosupport-不支持协议
eprototype-套接字的协议类型错误
erange-数学结果无法表示
erefused-已拒绝
eremchg-远程地址已更改
eremdev-远程设备
eremote-路径名命中远程文件系统
eremoteio-远程I / O错误
eremoterelease-删除
erofs-只读文件系统
erpcmismatch-错误的RPC版本
erremote-对象是远程的
eshutdown-套接字关闭后无法发送
esocktnosupport-不支持套接字类型
espipe-无效搜索
esrch-没有这样的过程
esrmnt-安装错误
estale-过时的远程文件句柄
esuccess-错误0
etime-计时器到期
etimedout-连接超时
etoomanyrefs-参考过多
etxtbsy-文本文件或伪设备繁忙
euclean-结构需要清洁
eunatch-未附加协议驱动程序
eusers-用户太多
eversion-版本不匹配
ewouldblock-操作将阻塞
exdev-跨域链接
exfull-消息表已满
nxdomain-找不到主机名或域名