inet
iNet
模块
iNet
模块摘要
访问TCP/IP协议。
描述
该模块提供对TCP/IP协议的访问。
另请参阅ERTS User's Guide: Inet Configuration
有关如何为IP通信配置Erlang运行时系统的更多信息。
以下两个内核配置参数影响在Erlang节点上打开的所有套接字的行为:
inet_default_connect_options
可以包含用于执行时返回的所有套接字的默认选项列表connect
。
inet_default_listen_options
可以包含发出listen
调用时使用的默认选项列表。
何时accept
发布,监听套接字选项的值将被继承。因此不需要这样的应用程序变量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传递给gethostbyaddr/1
字符串"150.236.20.73"
或元组{150, 236, 20, 73}
。
IPv 4提到了一些例子:
Address ip_address()
------- ------------
127.0.0.1 {127,0,0,1}
192.168.42.2 {192,168,42,2}
IPv 6地址示例:
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系统。
File
通常是本地文件系统中的文件路径名。它的操作系统长度有限,传统上为108字节。
binary()
按原样传递给操作系统,但a string()
按照system filename encoding mode.
其他地址是可能的,例如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()}
除了ip_address()
从套接字API函数返回的地址之外的地址。特别参见local_address().
该unspec
家族对应于AF_UNSPEC,并且如果另一方没有套接字地址则可能发生。该undefined
家庭只能发生在一个地址族的VM不承认万一。
posix() = exbadport | exbadseq |
file:posix()
一个由Unix中使用的POSIX错误代码以及大多数C编译器的运行时库命名的原子。参见章节POSIX Error Codes
。
socket()
参见gen_tcp:type-socket
和gen_udp:type-socket
。
address_family() = inet | inet6 | local
出口
close(Socket) -> ok
类型
关闭任何类型的套接字。
format_error(Reason) -> string()
类型
返回诊断错误字符串。有关可能的POSIX值和相应的字符串,请参见部分POSIX Error Codes
。
get_rc() ->
[{Par :: atom(), Val :: any()} |
{Par :: atom(), Val1 :: any(), Val2 :: any()}]
Inet
以记录的配置参数列表的形式返回配置数据库的状态。有关更多信息,请参阅ERTS User's Guide: Inet Configuration
。
只返回非默认值的实际参数,例如,不包含指定配置参数的其他来源的指令或用于清除参数的指令。
getaddr(Host, Family) -> {ok, Address} | {error, posix()}
类型
返回Host
作为整数元组的IP地址。Host
可以是IP地址,单个主机名或完全限定的主机名。
getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()}
类型
返回所有IP地址的列表Host
。Host
可以是IP地址,单个主机名或完全限定的主机名。
gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}
类型
返回hostent
具有指定地址的主机的记录。
gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()}
类型
返回hostent
用指定的主机名记录主机。
如果解析器选项inet6
是true
,则查找IPv6地址。如果失败,则查找IPv4地址并以IPv6映射的IPv4格式返回。
gethostbyname(Hostname, Family) ->
{ok, Hostent} | {error, posix()
}
类型
返回hostent
具有指定名称的主机的记录,限于指定的地址系列。
gethostname() -> {ok, Hostname}
类型
返回本地主机名。从未失败。
起义%28%29->{ok,Iflist}{Error,posix()}
类型
返回包含接口名称和接口地址的2元组列表。Ifname
是一个Unicode字符串。Hwaddr
例如,在以太网接口上,它是6字节的以太网地址(MAC地址(EUI-48地址))。
如果接口有多个地址,则元组{addr,Addr}
,{netmask,_}
和{broadaddr,_}
在结果列表中重复。如果你碰到一个有多个{flag,_}
或{hwaddr,_}
元组的接口,那么你有一个奇怪的接口或者可能是这个函数中的一个错误。元组{flag,_}
是强制性的,所有其他都是可选的。
不要过多依赖Flag
原子或Ifopt
元组的顺序。然而有一些规则:
- 紧接着
{addr,_}
如下{netmask,_}
。
- 紧接着如下
{broadaddr,_}
如果标志broadcast
是没有
设置和标志pointtopoint
的
设置。
- 跟随元组的任何
{netmask,_}
,{broadaddr,_}
或者{dstaddr,_}
元{addr,_}
组都涉及这个地址。
该元组{hwaddr,_}
不会在Solaris上返回,因为硬件地址历史上属于链路层,只有超级用户可以读取这些地址。
警告
在Windows上,数据是从不同的OS API函数中获取的,因此可以计算值Netmask
和Broadaddr
值,就像一些Flag
值一样。报告公然的错误。
getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()}
类型
获取一个或多个套接字选项。有关可用选项的列表,请参阅setopts/2
。
返回OptionValues
列表中元素的数量不一定对应于要求的选项数量。如果操作系统无法支持某个选项,则会将其排除在返回的列表中。只有在获取套接字选项是不可能的(即,套接字已关闭或原始请求中的缓冲区大小过大)时,才会返回错误元组。出于向后兼容性的原因,此行为被保留。
原始选项请求RawOptReq = {raw, Protocol, OptionNum, ValueSpec}
可用于获取有关套接字选项的信息,而不是(明确)由模拟器支持。原始套接字选项的使用使代码不可移植,但允许Erlang程序员利用当前平台上的不寻常功能。
RawOptReq
由标记,raw
后面跟着协议级别,选项号,以及要存储选项值的缓冲区的二进制或字节大小组成。当底层getsockopt
需要在参数字段中输入
时,将使用二进制。在这种情况下,二进制大小将与返回值所需的缓冲区大小相对应。RawOptReq
中提供的值对应getsockopt
于C socket API中调用的第二,第三和第四/第五个参数。存储在缓冲区中的值以二进制形式返回ValueBin
,其中所有值都以本地字节序进行编码。
询问和检查原始套接字选项需要有关当前操作系统和TCP堆栈的低级信息。
例子:
考虑一个Linux机器,其中TCP_INFO
可以使用选项来收集套接字的TCP统计信息。假设您在询问时tcpi_sacked
对struct tcp_info
填写的字段感兴趣TCP_INFO
。为了能够访问这些信息,您需要了解以下内容:
- 协议级别的数值
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()}
类型
获取套接字的一个或多个统计选项。
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
从套接字发送的字节数。
ntoa(IpAddress) -> Address | {error, einval}
类型
解析ip_address()
并返回IPv4或IPv6地址字符串。
parse_address(Address) -> {ok, IPAddress} | {error, einval}
类型
分析IPv4或IPv6地址字符串并返回一个ip4_address()
or ip6_address()
。接受缩短的IPv4地址字符串。
parse_ipv4_address(Address) -> {ok, IPv4Address} | {error, einval}
类型
解析IPv4地址字符串并返回一个ip4_address()
。接受缩短的IPv4地址字符串。
parse_ipv4strict_address(Address) ->
{ok,ipv4Address}{Error,einval}
类型
解析包含四个字段(即不
缩短)的IPv4地址字符串,并返回一个ip4_address()
。
parse_ipv6_address(Address) -> {ok, IPv6Address} | {error, einval}
类型
解析IPv6地址字符串并返回一个ip6_address()
。如果指定了IPv4地址字符串,则返回IPv4映射的IPv6地址。
parse_ipv6strict_address(Address) ->
{ok,ipv6Address}{Error,einval}
类型
解析IPv6地址字符串并返回一个ip6_address()
。难道不
接受IPv4地址。
parse_strict_address(Address) -> {ok, IPAddress} | {error, einval}
类型
分析IPv4或IPv6地址字符串并返回一个ip4_address()
or 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 Sockets API Extensions
。
peernames(Socket, Assoc) ->
{ok, {Address, Port}} | {error, posix()
}
类型
返回Assoc
套接字关联另一端的所有地址/端口号对列表。
此函数可以为多宿主套接字返回多个地址,例如SCTP套接字。对于其他套接字,它将返回一个元素列表。
请注意,参数Assoc
是由SCTP Sockets API Extensions
一对一样式套接字忽略的定义。0
不幸的是,特殊值意味着什么,因此它的一对多样式套接字的行为是不确定的。
port(Socket) -> {ok, Port} | {error, any()}
类型
返回套接字的本地端口号。
setopts(Socket, Options) -> ok | {error, posix()}
类型
为套接字设置一个或多个选项。
以下选项可用:
{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}
),则来自套接字的一条
数据消息将被发送到进程。setopts/2
要再收到一条
消息,必须再次选择{active, once}
。
如果值是N
-32768到32767(含)范围内的整数,则将该值添加到发送到控制进程的数据消息的套接字计数。套接字的默认消息数是0
。如果指定了负值,并且其大小等于或大于套接字的当前消息计数,则套接字的消息计数设置为0
。一旦套接字的消息数达到0
,无论是因为将接收到的数据消息发送到进程还是通过明确设置,然后通过特定于套接字类型的特定消息通知进程已经进入被动模式。一旦套接字进入被动模式,接收更多消息setopts/2
必须再次被调用以将套接字重新设置为活动模式。
使用{active, once}
或时{active, N}
,套接字在收到数据时会自动更改行为。这可能会与面向连接的套接字(即,gen_tcp
)相混淆,因为套接字的{active, false}
行为报告与具有行为的套接字不同{active, true}
。为了简化编程,插座,其中所述对等封闭,并且这被检测到,而在{active, false}
模式下,仍然会产生消息{tcp_closed,Socket}
时设置为{active, once}
,{active, true}
或{active, N}
模式。因此{tcp_closed,Socket}
,exit_on_close
当
套接字在模式{active, true}
和{active, false}
模式之间来回切换时,最终会出现消息,可能随后是套接字端口终止(取决于选项),这是安全的。但是,当
对端关闭被检测到,这完全取决于底层TCP / IP协议栈和协议。
注意{active, true}
模式不提供流量控制; 一个快速的发送者可以很容易地通过接收消息溢出接收者 {active, N}
模式也是如此,而消息计数大于零。
仅当您的高级协议提供自己的流量控制(例如,确认收到的消息)或交换的数据量较小时才使用活动模式。{active, false}
模式,使用{active, once}
模式或{active, N}
具有N
适合应用程序的值的模式提供流量控制。对方不能发送比接收器可以读取更快。
{broadcast, Boolean}
(UDP套接字)
启用/禁用发送广播的权限。
{buffer, Size}
驱动程序使用的用户级软件缓冲区的大小。不带选项混淆sndbuf和recbuf,对应于内核套接字缓冲区。val(buffer) >= max(val(sndbuf),val(recbuf))由于不必要的复制,建议不得不避免性能问题。val(buffer)在设置值sndbuf或recbuf设置时自动设置为上述最大值。但是,对于设置尺寸sndbuf和recbuf通常变得更大,我们鼓励您使用getopts/2来分析你的操作系统的行为。
请注意,这也是可以从单个recv呼叫接收的最大数据量。如果您使用高于正常的MTU,请考虑将缓冲区设置得更高。
{delay_send, Boolean}
通常,当Erlang进程发送到套接字时,驱动程序会立即尝试发送数据。如果失败,驱动程序使用任何可用的方法排队消息,只要操作系统声明它可以处理即可发送。设置{delay_send, true}
使所有
消息排队。发送到网络的消息越大,越少。该选项影响发送请求与Erlang进程的调度,而不是更改套接字的任何实际属性。该选项是特定于实现的。默认为false
。
{deliver, port | term}
当{active, true}
,数据以表格形式递送port
:{S, {data, [H1,..Hsz | Data]}}
或term
:{tcp, S, [H1..Hsz | Data]}
。
{dontroute, Boolean}
启用/禁用传出消息的绕行路由。
{exit_on_close, Boolean}
此选项设置为true
默认情况下。
将其设置为的唯一原因false
是,如果要在检测到关闭后继续向套接字发送数据(例如,对等方用于gen_tcp:shutdown/2
关闭写入端)。
{header, Size}
此选项仅binary
在创建套接字时指定了选项时才有意义。如果header
指定了选项,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
。而是使用distribution buffer busy limit
,这是一个类似的功能。
{high_watermark, Size}
(TCP/IP套接字)
当由ERTS套接字实现内部排队的数据量达到此限制时,套接字被设置为繁忙状态。默认为8 kB。
如果套接字消息队列繁忙或套接字本身繁忙,则数据发送到套接字的数据将暂停。
欲了解更多信息,请参见选项low_watermark
,high_msgq_watermark
和low_msqg_watermark
。
{ipv6_v6only, Boolean}
限制套接字仅使用IPv6,禁止任何IPv4连接。这仅适用于IPv6套接字(选件inet6
)。
在大多数平台上,该选项必须先在套接字上设置,然后再将其关联到地址。因此,在创建套接字时指定它并且在调用包含此描述的函数(setopts/2
)时不要使用它是合理的。
具有此选项的套接字的行为true
是唯一可移植的行为。当IPv6是所有流量使用IPv6的新概念时,FreeBSD现在不建议由FreeBSD({ipv6_v6only,false}
受支持的GENERIC内核)禁止使用FreeBSD(您可以使用它来覆盖建议的系统默认值),而在Windows中则不可以(在Windows IPv4和IPv6协议栈)。大多数Linux发行版仍然具有系统默认值false
。操作系统之间的政策转移将IPv6从IPv4流量中分离出来,因为逐步证明双栈实现是正确和安全的艰难和复杂。
在某些平台上,这个选项唯一允许的值是true
,例如OpenBSD和Windows。在这种情况下,尝试将此选项设置为false
在创建套接字时失败。
在不存在的平台上设置此选项将被忽略。获取此选项时不getopts/2
返回任何值,即返回的列表不包含{ipv6_v6only,_}
元组。在Windows上,该选项不存在,但它被模拟为带值的只读选项true
。
因此,true
在创建套接字时将此选项设置为永远不会失败,除非可能在您已将内核定制为仅允许的平台上执行false
,而在OpenBSD上可能是可行的(但很笨拙)。
如果使用回读选项值getopts/2
并且没有取值,则主机操作系统中不存在该选项。然后,监听同一端口的IPv6和IPv4套接字以及获取IPv4流量的IPv6套接字的行为将不再可预测。
{keepalive, Boolean}**
(TCP / IP套接字)**
当没有其他数据交换时,启用/禁用连接套接字上的定期传输。如果另一端没有响应,则认为连接中断,并向控制进程发送错误消息。默认为disabled
。
{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
。相反,他们使用distribution buffer busy limit
,这是一个相似的功能。
{low_watermark, Size}(TCP/IP sockets)
如果套接字处于繁忙状态,则当由ERTS套接字实现内部排队的数据量低于此限制时,套接字将设置为非忙状态。默认为4 kB。
当套接字消息队列和套接字不忙时,由于繁忙的消息队列或繁忙套接字而被暂停的发送器将被恢复。
欲了解更多信息,请参见选项high_watermark
,high_msgq_watermark
和low_msgq_watermark
。
{mode, Mode :: binary | list}
收到Packet
按照定义的方式发送Mode
。
{netns, Namespace :: file:filename_all()}
为套接字设置网络名称空间。参数Namespace
是定义命名空间的文件名,例如"/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的系统调用setns()
,例如在Linux内核3.0或更高版本中,因此只有在针对此类操作系统编译运行时系统时才存在。
虚拟机还需要提升权限,或者以超级用户身份运行,或者(针对Linux)CAP_SYS_ADMIN
按照其文档的要求运行setns(2)
。然而,测试过程中也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套接字似乎不支持网络命名空间。
Namespace
是一个文件名,并按照模块中的讨论进行编码和解码file
,但以下情况除外:
- 仿真器标志
+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 instances
。
list
已收到Packet
以列表形式发送。
binary
收到Packet
以二进制形式提供。
{nodelay, Boolean}**
(TCP/IP sockets)**
如果Boolean == true
,TCP_NODELAY
对于套接字打开选项,这意味着也会立即发送少量数据。
{packet, PacketType}**
(TCP/IP sockets)**
定义用于套接字的数据包类型。可能的值:
raw | 0
没有包装是做的。
1 | 2 | 4
数据包包含一个标题,指定数据包中的字节数,然后是该字节数。标题长度可以是一个,两个或四个字节,并且包含一个大端字节顺序的无符号整数。每个发送操作都会生成标题,并且标题在每个接收操作中都被剥离。
4字节的头被限制在2GB。
asn1 | cdr | sunrm | fcgi | tpkt | line
这些数据包类型仅对接收产生影响。发送数据包时,应用程序负责提供正确的标题。然而,在接收时,对于每个接收到的完整分组,将一个消息发送到控制过程,并且类似地,每次调用gen_tcp:recv/2,3
返回一个完整的分组。标题没有
被删除。
数据包类型的含义如下:
asn1
-ASN.1误码率
sunrm
- Sun的RPC编码
cdr
- CORBA(GIOP 1.1)
fcgi
-快速CGI
tpkt
-TPKT格式RFC 1006
line
- 线路模式,数据包是以换行符行结束的行,比接收缓冲区长的行被截断
http | http_bin
超文本传输协议。数据包以ERTS中HttpPacket
描述的格式返回erlang:decode_packet/3
。处于被动模式的套接字{ok, HttpPacket}
从gen_tcp:recv
活动套接字发送消息时返回{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)**
设置面向行的协议(line
)的行分隔字符。默认为$\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
下文)。默认为infinity
。
{send_timeout_close, Boolean}
只允许面向连接的套接字。
与send_timeout
发送操作返回时指定是否要自动关闭套接字一起使用{error,timeout}
。推荐的设置是true
自动关闭套接字。默认是false
因为向后兼容。
{show_econnreset, Boolean}**
(TCP/IP sockets)**
当此选项设置false
为默认值时,从TCP对等端收到的RST被视为正常关闭(就像发送了FIN一样)。来电者gen_tcp:recv/2
获取{error, closed}
。在主动模式下,控制进程收到一条{tcp_close, Socket}
消息,指示对等关闭了连接。
通过设置该选项,true
您可以区分正常关闭的连接和TCP对等方中断(有意或无意)的连接。呼叫gen_tcp:recv/2
返回{error, econnreset}
。在主动模式下,控制进程{tcp_error, Socket, econnreset}
在通常{tcp_closed, Socket}
情况下收到消息,就像其他套接字错误一样。当检测到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
在执行此操作的平台上设置级别选项。不同系统之间的行为和允许范围有所不同。该选项在未实现的平台上被忽略。谨慎使用。
{tclass, Integer}
IPV6_TCLASS IP
在执行此操作的平台上设置级别选项。不同系统之间的行为和允许范围有所不同。该选项在未实现的平台上被忽略。谨慎使用。
除了这些选项之外,还可以使用原始
选项规范。原始
选项被指定为四元组的元组,从标签开始raw
,随后是协议级别,选项号和指定为二进制的选项值。这对应setsockopt
于C socket API中调用的第二,第三和第四个参数。选项值必须在平台的本地代码中进行编码,并且如果需要结构,则必须遵循特定平台上的结构对齐约定。
使用原始套接字选项需要详细了解当前操作系统和TCP堆栈。
例子:
这个例子涉及使用原始选项。考虑一个Linux系统,您希望在堆栈中设置TCP_LINGER2
协议级别的选项IPPROTO_TCP
。你知道在这个特定的系统上它默认为60(秒),但是你想把它降低到30对于一个特定的套接字。选项TCP_LINGER2
没有被明确支持inet
,但是您知道协议级别转换为数字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}]),
诸如这些例子的代码本质上是不可移植的,甚至同一平台上相同操作系统的不同版本可以对这种类型的选项操作做出不同的响应。小心使用。
请注意,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()
}
类型
返回指定关联的套接字的所有本地地址/端口号对列表Assoc
。
此函数可以为多宿主套接字返回多个地址,例如SCTP套接字。对于其他套接字,它将返回一个元素列表。
请注意,参数Assoc
是由SCTP Sockets API Extensions
一对一样式套接字忽略的定义。对于一对多套接字,特殊值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
-不使用武力安装脏飞秒
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
-三级重置
elbin
-ELBIN
elibacc
-无法访问所需的共享库
elibbad
-访问已损坏的共享库
elibexec
-不能直接执行共享库
elibmax
-试图链接到比系统限制更多的共享库中
elibscn
-.lib
部分a.out
已损坏
elnrng
-链接号超出范围
eloop
-符号链接太多
emfile
-打开的档案太多
emlink
-链接太多
emsgsize
-信息太长
emultihop
-多跳尝试
enametoolong
-文件名太长
enavail
-得不到
enet
-ENET
enetdown
-网络瘫痪
enetreset
-重置时网络断开连接
enetunreach
-网络是不可及的
enfile
-文件表溢出
enoano
- 阳极表溢出
enobufs
-没有缓冲空间
enocsi
-没有CSI结构
enodata
-没有数据
enodev
-没有这种装置
enoent
-没有这类档案或目录
enoexec
-EXEC格式错误
enolck
-没有锁
enolink
-联系已被切断
enomem
-内存不足
enomsg
-没有所需类型的消息
enonet
-机器不在网络上
enopkg
-包件未安装
enoprotoopt
-不良协议选择
enospc
-设备上没有空间
enosr
-流资源是否耗尽流设备
enosym
-未解决的符号名称
enosys
- 功能未实现
enotblk
- 需要阻止设备
enotconn
- Socket没有连接
enotdir
-不是目录
enotempty
-目录不空
enotnam
- 不是一个命名文件
enotsock
- 在非插座上进行套接字操作
enotsup
-没有支助的行动
enotty
- 不适当的设备ioctl
enotuniq
- 名称在网络上不唯一
enxio
- 没有这样的设备或地址
eopnotsupp
- 套接字不支持操作
eperm
- 不是所有者
epfnosupport
- 不支持协议族
epipe
- 管道破损
eproclim
- 进程太多
eprocunavail
- 程序错误
eprogmismatch
-错误的程序版本
eprogunavail
-RPC程序不可用
eproto
-协议错误
eprotonosupport
-议定书未获支持
eprototype
-套接字协议类型错误
erange
-无法表示的数学结果
erefused
-EREFUSED
eremchg
-更改远程地址
eremdev
-遥控装置
eremote
-路径名击中远程文件系统
eremoteio
-远程I/O错误
eremoterelease
-EREMOTERELEASE
erofs
-只读文件系统
erpcmismatch
-RPC版本错误
erremote
-对象是远程的
eshutdown
-套接字关闭后无法发送
esocktnosupport
-套接字类型不支持
espipe
-无效寻求
esrch
-没有这种程序
esrmnt
-sr装入错误
estale
-陈旧的远程文件句柄
esuccess
-错误0
etime
-计时器过期
etimedout
-连接超时
etoomanyrefs
-提及太多
etxtbsy
-文本文件或伪设备繁忙
euclean
-结构需要清理
eunatch
-礼宾驱动程序未附
eusers
-用户太多
eversion
-版本错配
ewouldblock
-行动将阻止
exdev
-跨域链接
exfull
-电文表已满
nxdomain
-找不到主机名或域名