查看源代码 inet (内核 v10.2)
访问网络协议。
此模块与 gen_tcp
、gen_udp
和 gen_sctp
一起,提供了对基于 IP 的 TCP、SCTP 和 UDP 网络协议的访问,以及对本地(unix)地址域/协议域上的流和数据报协议的访问。
另请参阅 ERTS 用户指南:Inet 配置,了解有关如何为 IP 通信配置 Erlang 运行时系统的更多信息。
以下两个内核配置参数会影响在 Erlang 节点上打开的所有 gen_tcp
套接字的行为
inet_default_connect_options
可以包含一个默认选项列表,用于由gen_tcp:connect/2,3,4
](gen_tcp:connect/2
) 调用创建的所有套接字。inet_default_listen_options
可以包含一个默认选项列表,用于由gen_tcp:listen/2
调用创建的套接字。
对于 gen_tcp:accept/1,2
调用,会继承监听套接字选项的值。 因此,没有对应的 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,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}}
POSIX 错误代码
e2big
- 参数列表过长eacces
- 权限被拒绝eaddrinuse
- 地址已被使用eaddrnotavail
- 无法分配请求的地址eadv
- 广告错误eafnosupport
- 协议族不支持的地址族eagain
- 资源暂时不可用ealign
- EALIGNealready
- 操作正在进行中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
- 3 级重置elbin
- ELBINelibacc
- 无法访问所需的共享库elibbad
- 访问损坏的共享库elibexec
- 无法直接执行共享库elibmax
- 尝试链接到超出系统限制的更多共享库elibscn
-a.out
中的.lib
部分已损坏elnrng
- 链接号超出范围eloop
- 符号链接的级别过多emfile
- 打开的文件过多emlink
- 链接过多emsgsize
- 消息过长emultihop
- 尝试了多跳enametoolong
- 文件名过长enavail
- 不可用enet
- ENETenetdown
- 网络已关闭enetreset
- 网络在重置时断开连接enetunreach
- 网络无法访问enfile
- 文件表溢出enoano
- Anode 表溢出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
- EREFUSEDeremchg
- 远程地址已更改eremdev
- 远程设备eremote
- 路径名命中远程文件系统eremoteio
- 远程 I/O 错误eremoterelease
- EREMOTERELEASEerofs
- 只读文件系统erpcmismatch
- 错误的 RPC 版本erremote
- 对象是远程的eshutdown
- 套接字关闭后无法发送esocktnosupport
- 不支持的套接字类型espipe
- 无效的查找esrch
- 没有这样的进程esrmnt
- Srmount 错误estale
- 过时的远程文件句柄esuccess
- 错误 0etime
- 计时器已过期etimedout
- 连接超时etoomanyrefs
- 引用过多etxtbsy
- 文本文件或伪设备忙euclean
- 结构需要清理eunatch
- 未附加协议驱动程序eusers
- 用户过多eversion
- 版本不匹配ewouldblock
- 操作将阻塞exdev
- 跨设备链接exfull
- 消息表已满nxdomain
- 找不到主机名或域名
概要
类型:导出的数据类型
辅助数据/控制消息。
通用网络地址。
一个描述主机的记录;包括名称和地址。
socket/0
的实现后端选择器。
local
族(AF_LOCAL | AF_UNIX
)的网络地址
非 IP 网络地址。
此模块及其兄弟模块识别的套接字。
函数
取消套接字监视器。
关闭任何类型的套接字。
将错误代码格式化为 string/0
。
获取 inet
配置。
在特定地址族中将主机解析为地址。
在特定地址族中将主机解析为地址列表。
将地址解析(反向)为 #hostent{}
记录。
将主机名解析为 #hostent{}
记录。
在特定地址族中将主机名解析为 #hostent{}
记录。
获取本地主机名。
获取接口名称和地址。
在特定命名空间中获取接口名称和地址。
获取套接字的一个或多个选项。
等同于 getstat/2
。
获取套接字的一个或多个统计信息选项。
列出网络套接字。
列出网络套接字。
获取有关套接字的信息。
在 IPv4 地址和 IPv4 映射的 IPv6 地址之间转换。
测试是否为 IP 地址。
测试是否为 IPv4 地址。
测试是否为 IPv6 地址。
启动套接字监视器。
将 ip_address/0
解析为 IPv4 或 IPv6 地址字符串。
将 IP 地址字符串解析为 ip_address/0
。
将(宽松的)IPv4 地址字符串解析为 ip4_address/0
。
将 IPv4 地址字符串解析为 ip4_address/0
。
将(宽松的)IPv6 地址字符串解析为 ip6_address/0
。
将 IPv6 地址字符串解析为 ip6_address/0
。
将 IP 地址字符串解析为 ip_address/0
。
返回套接字远程端的地址。
返回套接字所有远程端的地址。
返回套接字的本地端口号。
设置套接字的一个或多个选项。
返回套接字的本地地址和端口号。
返回套接字的所有本地地址。
类型:导出的数据类型
-type address_family() :: inet | inet6 | local.
辅助数据/控制消息。
与数据包一起接收的辅助数据,从 TCP 套接字使用套接字选项 pktoptions
读取,或在调用 gen_udp:send/4
或 gen_udp:send/5
时设置。
这些值对应于当前活动的套接字 选项 recvtos
、recvtclass
和 recvttl
,或者对于单个发送操作,对应于覆盖当前活动套接字选项的选项。
-type family_address() :: inet_address() | inet6_address() | local_address().
通用网络地址。
形式为 {Family, Destination}
的通用网络地址格式,其中 Family
是一个原子,例如 local
,Destination
的格式取决于 Family
。Destination
是一个完整的地址(例如,带有端口号的 IP 地址)。
-type hostent() :: #hostent{h_name :: inet:hostname(), h_aliases :: [inet:hostname()], h_addrtype :: inet | inet6, h_length :: non_neg_integer(), h_addr_list :: [inet:ip_address()]}.
一个描述主机的记录;包括名称和地址。
对应于 C
:例如 gethostbyname(3)
返回的 struct hostent
。
该记录在 Kernel 包含文件 "inet.hrl"
中定义。
将以下指令添加到模块
-include_lib("kernel/include/inet.hrl").
-type inet_backend() :: {inet_backend, inet | socket}.
socket/0
的实现后端选择器。
选择 [套接字](socket/0
) 的实现后端。当前的默认值是 inet
,它使用 inet_drv.c
来调用平台的套接字 API。值 socket
改为使用 socket
模块及其 NIF 实现。
这是一个临时选项,将在未来的版本中被忽略。
-type ip4_address() :: {0..255, 0..255, 0..255, 0..255}.
-type ip6_address() :: {0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535}.
-type ip_address() :: ip4_address() | ip6_address().
local
族(AF_LOCAL | AF_UNIX
)的网络地址
此地址族,也称为“Unix 域套接字”,仅在类 Unix 系统上有效。
File
通常是本地文件系统中的文件路径名。其长度受操作系统的限制,传统上为 108 个字节。
binary/0
按原样传递给操作系统,但是 string/0
根据 系统文件名编码模式 进行编码。
其他地址也是可能的,例如,Linux 实现了“抽象地址”。请参阅系统上 Unix 域套接字的文档,通常在手册第 7 节中为 unix
。
在大多数可以使用此地址族的 API 函数中,端口号必须为 0
。
-type port_number() :: 0..65535.
-type 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().
POSIX 错误代码 atom/0
。
一个从 Unix 中使用的 POSIX 错误代码以及大多数 C 编译器的运行时库中命名的原子。请参阅 POSIX 错误代码 部分。
非 IP 网络地址。
从套接字 API 函数返回的除了 ip_address/0
之外的地址。特别参见 local_address/0
。unspec
族对应于 AF_UNSPEC
,如果另一侧没有套接字地址,则可能出现。undefined
族只能在虚拟机无法识别地址族的极不可能情况下出现。
-type socket() :: port() | module_socket().
此模块及其兄弟模块识别的套接字。
请参阅 gen_tcp:socket/0
和 gen_udp:socket/0
。
-type socket_address() :: ip_address() | any | loopback | local_address().
-type socket_getopt() :: gen_sctp:option_name() | gen_tcp:option_name() | gen_udp:option_name().
-type socket_optval() :: gen_sctp:option_value() | gen_tcp:option() | gen_udp:option() | gen_tcp:pktoptions_value().
-type socket_protocol() :: tcp | udp | sctp.
-type socket_setopt() :: gen_sctp:option() | gen_tcp:option() | gen_udp:option().
-type stat_option() ::
recv_cnt | recv_max | recv_avg | recv_oct | recv_dvi | send_cnt | send_max | send_avg |
send_oct | send_pend.
类型:内部数据类型
-type getifaddrs_ifopts() :: [Ifopt :: {flags, Flags :: [up | broadcast | loopback | pointtopoint | running | multicast]} | {addr, Addr :: ip_address()} | {netmask, Netmask :: ip_address()} | {broadaddr, Broadaddr :: ip_address()} | {dstaddr, Dstaddr :: ip_address()} | {hwaddr, Hwaddr :: [byte()]}].
接口地址描述列表。
从 getifaddrs/0,1
为命名接口返回的列表,从 POSIX API 函数 getaddrinfo()
返回的数据转换而来。
Hwaddr
是硬件相关的,例如,在以太网接口上,它是 6 字节的以太网地址(MAC 地址(EUI-48 地址))。
如果接口具有多个地址,则元组 {addr,Addr}
、{netmask,Netmask}
,以及可能的 {broadaddr,Broadaddr}
或 {dstaddr,Dstaddr}
将在列表中重复。如果接口对于不同的地址族具有不同的标志,则该接口可能具有多个 {flag,_}
元组。
关于多个 {hwaddr,Hwaddr}
元组,很难说出明确的信息。元组 {flag,Flags}
是必需的,所有其他元组都是可选的。
不要太依赖 Flags
原子或 Ifopt
元组的顺序。但是,有一些规则
{flag,_}
元组适用于其后的所有其他元组。{addr,_}
之后紧跟着{netmask,_}
。- 此后紧接着,如果
broadcast
是Flags
的成员,则可能跟随{broadaddr,_}
,如果pointtopoint
是Flags
的成员,则可能跟随{dstaddr,_}
。对于相同的{addr,_}
,{dstaddr,_}
和{broadaddr,_}
都不会出现。 - 跟随
{addr,Addr}
元组的任何{netmask,_}
、{broadaddr,_}
或{dstaddr,_}
元组都与地址Addr
相关。
在 Solaris 上不返回元组 {hwaddr,_}
,因为硬件地址历史上属于链路层,并且 Solaris API 函数 getaddrinfo()
不返回它。
警告
在 Windows 上,数据是从不同的 OS API 函数中获取的,因此
Netmask
和Broadaddr
值可以计算得出,就像一些Flags
值一样。
-type inet6_address() :: {inet6, {ip6_address() | any | loopback, port_number()}}.
inet6
族(AF_INET6
,IPv6)的网络地址
警告
此地址格式目前是实验性的,为了完整性,使所有地址族都有一个
{Family, Destination}
表示。
-type inet_address() :: {inet, {ip4_address() | any | loopback, port_number()}}.
inet
族(AF_INET
,IPv4)的网络地址
警告
此地址格式目前是实验性的,为了完整性,使所有地址族都有一个
{Family, Destination}
表示。
类型
函数
取消套接字监视器。
如果 MRef
是调用进程通过调用 monitor/1
获取的引用,则此监视器将被移除。如果监视器已被移除,则不会发生任何事情。
返回的值是以下之一
true
- 找到了监视器并已将其移除。在这种情况下,尚未传递与此监视器对应的'DOWN'
消息,并且不会传递。false
- 未找到监视器,无法将其移除。可能因为监视器已触发,并且在调用者消息队列中存在相应的'DOWN'
消息。
-spec close(Socket) -> ok when Socket :: socket().
关闭任何类型的套接字。
将错误代码格式化为 string/0
。
返回诊断错误字符串。有关可能的 POSIX 值和相应的字符串,请参阅 POSIX 错误代码部分。
获取 inet
配置。
以记录的配置参数列表的形式返回 inet
配置数据库的状态。有关更多信息,请参阅 ERTS 用户指南:Inet 配置。
仅返回具有非默认值的实际参数,例如,不返回指定配置参数其他来源的指令,也不返回清除参数的指令。
-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when Host :: ip_address() | hostname(), Family :: address_family(), Address :: ip_address().
在特定地址族中将主机解析为地址。
返回 Host
的 IP 地址,形式为整数元组。Host
可以是 IP 地址、单个 hostname/0
或完全限定的 hostname/0
。
-spec getaddrs(Host, Family) -> {ok, Addresses} | {error, posix()} when Host :: ip_address() | hostname(), Family :: address_family(), Addresses :: [ip_address()].
在特定地址族中将主机解析为地址列表。
返回 Host
的所有 IP 地址的列表。Host
可以是 IP 地址、单个 hostname/0
或完全限定的 hostname/0
。
-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()} when Address :: string() | ip_address(), Hostent :: hostent().
将地址解析(反向)为 #hostent{}
记录。
返回具有指定地址的主机的 #hostent{}
记录。
-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()} when Hostname :: hostname(), Hostent :: hostent().
将主机名解析为 #hostent{}
记录。
返回具有指定 Hostname
的主机的 #hostent{}
记录。
此函数使用解析器,通常是本机 (OS) 解析器。
如果解析器选项 inet6
为 true
,则会查找 IPv6 地址。
有关解析器配置的信息,请参阅 ERTS 用户指南:Inet 配置。
许多解析器的一个怪癖是将整数字符串解释为 IP 地址。例如,整数字符串 "3232235521" 和字符串 "192.168.0.1" 都被转换为 IP 地址 {192,168,0,1}
。
-spec gethostbyname(Hostname, Family) -> {ok, Hostent} | {error, posix()} when Hostname :: hostname(), Family :: address_family(), Hostent :: hostent().
在特定地址族中将主机名解析为 #hostent{}
记录。
返回具有指定 Hostname
的主机的 #hostent{}
记录,限制为指定的地址 Family
。
另请参阅 gethostbyname/1
。
-spec gethostname() -> {ok, Hostname} when Hostname :: string().
获取本地主机名。
返回本地主机名。永远不会失败。
-spec getifaddrs() -> {ok, [{Ifname :: string(), Ifopts :: getifaddrs_ifopts()}]} | {error, posix()}.
获取接口名称和地址。
返回包含接口名称和接口地址的 2 元组列表。Ifname
是 Unicode 字符串,Ifopts
是接口地址描述元组的列表。
接口地址描述元组记录在 Ifopts
值的类型下。
-spec getifaddrs([Option :: inet_backend() | {netns, Namespace :: file:filename_all()}] | socket()) -> {ok, [{Ifname :: string(), Ifopts :: getifaddrs_ifopts()}]} | {error, posix()}.
在特定命名空间中获取接口名称和地址。
等效于 getifaddrs/0
,但接受 Option
{netns, Namespace}
,在支持此功能的平台(Linux)上,为 OS 调用设置网络命名空间。此外,如果选项 'inet_backend' 在选项列表中是 *第一个*,则将使用指定的后端(对于 'inet',使用 inet,对于 'socket',将使用等效的网络函数)。
请参阅 setopts/2
下的套接字选项 {netns, Namespace}
。
-spec getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()} when Socket :: socket(), Options :: [socket_getopt()], OptionValues :: [socket_optval()].
获取套接字的一个或多个选项。
从 Socket
中获取列表 Options
中的所有选项。有关可用选项的列表,请参阅 setopts/2
。另请参阅 socket_optval()
引用的协议特定类型的描述。
返回的 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.
最好在执行任何类似此代码的操作之前检查机器类型、操作系统和内核版本。
-spec getstat(Socket) -> {ok, OptionValues} | {error, posix()} when Socket :: socket(), OptionValues :: [{stat_option(), integer()}].
等同于 getstat/2
。
-spec getstat(Socket, Options) -> {ok, OptionValues} | {error, posix()} when Socket :: socket(), Options :: [stat_option()], OptionValues :: [{stat_option(), integer()}].
获取套接字的一个或多个统计信息选项。
getstat(Socket)
等效于 getstat(Socket, [recv_avg, recv_cnt, recv_dvi, recv_max, recv_oct, send_avg, send_cnt, send_pend, send_max, send_oct])
。
以下选项可用
recv_avg
- 套接字接收到的数据包的平均大小(以字节为单位)。recv_cnt
- 套接字接收到的数据包的数量。recv_dvi
- 套接字接收到的平均数据包大小偏差(以字节为单位)。recv_max
- 套接字接收到的最大数据包的大小(以字节为单位)。recv_oct
- 套接字接收到的字节数。send_avg
- 从套接字发送的数据包的平均大小(以字节为单位)。send_cnt
- 从套接字发送的数据包的数量。send_pend
- 等待套接字发送的字节数。send_max
- 从套接字发送的最大数据包的大小(以字节为单位)。send_oct
- 从套接字发送的字节数。
-spec i() -> ok.
等同于 tcp
、udp
和 sctp
协议的 i/1
。
-spec i(show_ports | socket_protocol() | [i_option()]) -> ok.
列出网络套接字。
对于参数 Proto
,等效于 i(Proto, Options)
,其中 Options
是 i_option/0
中的所有 atom/0
的列表。
对于参数 Options
,等效于 `i(Proto, Options),其中 Proto
为 tcp
、udp
和 sctp
。对于参数 show_ports
(自 OTP 27.0 起),等效于 `i(Proto, Options),其中 Option
是 i_option/0
中所有选项的列表,其中 ShowPorts = true
。
-spec i(socket_protocol(), show_ports | (Options :: [i_option()])) -> ok.
列出网络套接字。
列出终端上的所有 TCP、UDP 和 SCTP 套接字,包括由 Erlang 运行时系统创建的套接字以及由应用程序创建的套接字。
以下选项可用
port
- 端口的内部索引。module
- 套接字的回调模块。recv
- 套接字接收的字节数。sent
- 套接字发送的字节数。owner
- 套接字的所有者进程。local_address
- 套接字的本地地址。foreign_address
- 连接另一端的地址和端口。state
- 连接状态。type
- STREAM、DGRAM 或 SEQPACKET。
Options
参数也可以是 (自 OTP 27.0 起)
show_ports
- 不要将端口号('local_address' 和 'foreign_address' 的端口号)转换为服务名称。
获取有关套接字的信息。
返回一个包含关于套接字的杂项信息的项。
-spec ipv4_mapped_ipv6_address(ip_address()) -> ip_address().
在 IPv4 地址和 IPv4 映射的 IPv6 地址之间转换。
将 IPv4 地址转换为 IPv4 映射的 IPv6 地址,反之亦然。当从 IPv6 地址转换时,除了低 2 个字之外的所有字都会被忽略,因此此函数也适用于某些其他类型的 IPv6 地址,而不是 IPv4 映射的地址。
-spec is_ip_address(IPAddress) -> boolean() when IPAddress :: ip_address() | term().
测试是否为 IP 地址。
测试参数 IPAddress
是否为 ip_address/0
,如果是,则返回 true
,否则返回 false
。
-spec is_ipv4_address(IPv4Address) -> boolean() when IPv4Address :: ip4_address() | term().
测试是否为 IPv4 地址。
测试参数 IPv4Address
是否为 ip4_address/0
,如果是,则返回 true
,否则返回 false
。
-spec is_ipv6_address(IPv6Address) -> boolean() when IPv6Address :: ip6_address() | term().
测试是否为 IPv6 地址。
测试参数 IPv6Address
是否为 ip6_address/0
,如果是,则返回 true
,否则返回 false
。
启动套接字监视器。
如果要监视的 Socket
不存在,或者当监视器被触发时,将发送一个具有以下模式的 'DOWN'
消息
{'DOWN', MonitorRef, Type, Object, Info}
MonitorRef
- 此函数的返回值。Type
- 套接字的类型,可以是以下atom/0
之一:port
或socket
。Object
- 被监视的实体,即触发事件的套接字。Info
- 套接字的终止原因或nosock
(调用此函数时Socket
不存在)。
多次调用同一个 Socket
的 inet:monitor/1
不是错误;每次调用都会创建一个监视器。
当套接字以任何方式关闭时,例如 API 调用、远程端关闭、所有者退出时由信号关闭等,都会触发监视器。
-spec ntoa(IpAddress) -> Address | {error, einval} when Address :: string(), IpAddress :: ip_address().
将 ip_address/0
解析为 IPv4 或 IPv6 地址字符串。
-spec parse_address(Address) -> {ok, IPAddress} | {error, einval} when Address :: string(), IPAddress :: ip_address().
将 IP 地址字符串解析为 ip_address/0
。
根据哪个解析成功,返回一个 ip4_address/0
或一个 ip6_address/0
。
接受一个简短形式的 IPv4 地址字符串,如 parse_ipv4_address/1
。
-spec parse_ipv4_address(Address) -> {ok, IPv4Address} | {error, einval} when Address :: string(), IPv4Address :: ip4_address().
将(宽松的)IPv4 地址字符串解析为 ip4_address/0
。
接受简短形式的 IPv4 地址字符串(少于 4 个字段),例如 "127.1"
或 "0x7f000001"
。
-spec parse_ipv4strict_address(Address) -> {ok, IPv4Address} | {error, einval} when Address :: string(), IPv4Address :: ip4_address().
将 IPv4 地址字符串解析为 ip4_address/0
。
需要包含四个字段的 IPv4 地址字符串,即:不是简短形式的地址字符串。
-spec parse_ipv6_address(Address) -> {ok, IPv6Address} | {error, einval} when Address :: string(), IPv6Address :: ip6_address().
将(宽松的)IPv6 地址字符串解析为 ip6_address/0
。
还接受一个(宽松的)IPv4 地址字符串,如 parse_ipv4_address/1
,并返回一个 IPv4 映射的 IPv6 地址。
-spec parse_ipv6strict_address(Address) -> {ok, IPv6Address} | {error, einval} when Address :: string(), IPv6Address :: ip6_address().
将 IPv6 地址字符串解析为 ip6_address/0
。
不接受 IPv4 地址字符串。但是,IPv6 地址字符串允许 IPv4 尾部,如下所示:"::127.0.0.1"
(与 "::7f00:0001"
相同)。
-spec parse_strict_address(Address) -> {ok, IPAddress} | {error, einval} when Address :: string(), IPAddress :: ip_address().
将 IP 地址字符串解析为 ip_address/0
。
类似于 parse_address/1
,但是不接受简短形式的 IPv4 地址字符串。
-spec peername(Socket :: socket()) -> {ok, {ip_address(), port_number()} | returned_non_ip_address()} | {error, posix()}.
返回套接字远程端的地址。
返回连接另一端的地址和端口。
请注意,对于 SCTP 套接字,此函数仅返回套接字的一个对等地址。函数 peernames/1,2
返回所有地址。
-spec peernames(Socket :: socket()) -> {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.
等同于 peernames(Socket, 0)
。
请注意,此函数对于 SCTP 一对多样式套接字的行为未由 SCTP 套接字 API 扩展定义。
-spec peernames(Socket, Assoc) -> {ok, [{Address, Port}]} | {error, posix()} when Socket :: socket(), Assoc :: #sctp_assoc_change{state :: term(), error :: term(), outbound_streams :: term(), inbound_streams :: term(), assoc_id :: term()} | gen_sctp:assoc_id(), Address :: ip_address(), Port :: non_neg_integer().
返回套接字所有远程端的地址。
返回套接字的关联 Assoc
的远程端的所有地址/端口号对的列表。
此函数可以为多宿主套接字(例如 SCTP 套接字)返回多个地址。对于其他套接字,它返回一个单元素列表。
请注意,参数 Assoc
由 SCTP 套接字 API 扩展 定义为对一对一样式套接字忽略。特殊值 0
的含义不幸地未定义,因此对于一对多样式套接字的行为也是如此。
-spec port(Socket) -> {ok, Port} | {error, any()} when Socket :: socket(), Port :: port_number().
返回套接字的本地端口号。
-spec setopts(Socket, Options) -> ok | {error, posix()} when Socket :: socket(), Options :: [socket_setopt()].
设置套接字的一个或多个选项。
在 Socket
上设置 Options
列表。
以下选项可用
{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, false}
模式下检测到这种情况时,设置为{active, once}
、{active, true}
或{active, N}
模式的套接字仍会生成消息{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
的值设置为适合应用程序的值来提供流控制。另一方不能比接收方读取的速度更快地发送数据。{buffer, Size}
- 驱动程序使用的用户级缓冲区的大小。不要与对应于内核套接字缓冲区的sndbuf
和recbuf
选项混淆。对于 TCP,建议val(buffer) >= val(recbuf)
,以避免因不必要的复制而导致性能问题。对于 UDP,也适用相同的建议,但最大值不应大于网络路径的 MTU。val(buffer)
在设置recbuf
时会自动设置为上述最大值。但是,由于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
来关闭写入端。{exclusiveaddruse, Boolean}
- 在 Windows 上启用/禁用独占地址/端口使用。也就是说,通过启用此选项,可以防止其他套接字绑定到同一地址/端口。默认情况下,此选项处于禁用状态。也就是说,其他套接字可以通过设置{reuseaddr, true}
并结合{reuseport, true}
来使用相同的地址/端口,除非Socket
上已设置{exclusiveaddruse, true}
。在非 Windows 系统上,此选项会被静默忽略。注意
此选项当前不支持使用
inet_backend = socket
创建的套接字{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
的使用。而是使用 分发缓冲区繁忙限制,这是一个类似的功能。{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 推荐(可以使用{ipv6_v6only,false}
来覆盖建议的系统默认值),被 OpenBSD(支持的 GENERIC 内核)禁止,并且在 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 套接字) - 启用/禁用在没有交换其他数据时在已连接的套接字上的定期传输。如果另一端没有响应,则认为连接已断开,并且会向控制进程发送错误消息。默认为false
。{linger, {true|false, Seconds}}
- 确定在close/1
套接字调用中刷新未发送数据的超时时间(以秒为单位)。第一个组件是是否启用 linger,第二个组件是刷新超时时间(以秒为单位)。有 3 个选项
{false, _}
- close/1 或 shutdown/2 立即返回,不等待数据刷新,关闭在后台发生。{true, 0}
- 在连接关闭时中止连接。丢弃发送缓冲区中仍然存在的任何数据,并将 RST 发送到对等方。这避免了 TCP 的 TIME_WAIT 状态,但留下创建此连接的另一个“化身”的可能性。
{true, Time} when Time > 0
- close/1 或 shutdown/2 将不会返回,直到套接字的所有排队消息都已成功发送或达到 linger 超时时间 (Time) 为止。
{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 套接字) - 如果套接字处于繁忙状态,则当 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
,以及getifaddrs/1
。此选项使用 Linux 特定的系统调用
setns()
,例如 Linux 内核 3.0 或更高版本,因此仅当为这种操作系统编译运行时系统时才存在。虚拟机还需要提升的权限,要么以超级用户身份运行,要么(对于 Linux)根据
setns(2)
的文档,拥有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 套接字似乎不支持网络命名空间。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 实例。
list
- 收到的Packet
将作为列表传递。binary
- 收到的Packet
将作为二进制文件传递。{nodelay, Boolean}
(TCP/IP 套接字) - 如果Boolean == true
,则为套接字启用TCP_NODELAY
选项,这意味着也会立即发送少量数据。此选项不支持
domain = local
,但如果inet_backend =/= socket
,此错误将被忽略。{nopush, Boolean}
(TCP/IP 套接字) - 在 BSD 上转换为TCP_NOPUSH
,在 Linux 上转换为TCP_CORK
。如果
Boolean == true
,则为套接字启用相应的选项,这意味着将累积少量数据,直到有足够一个 MSS 大小的数据可用或此选项被禁用为止。请注意,虽然
TCP_NOPUSH
套接字选项在 OSX 上可用,但其语义非常不同(例如,取消设置它不会导致立即发送累积的数据)。因此,在 OSX 上有意忽略nopush
选项。{packet, PacketType}
(TCP/IP 套接字) - 定义套接字要使用的包类型。可能的值raw | 0
- 不进行任何打包。1 | 2 | 4
- 包由一个指定包中字节数的标头组成,后跟该数量的字节。标头长度可以是一个、两个或四个字节,并且包含大端字节顺序的无符号整数。每次发送操作都会生成标头,并且每次接收操作都会删除标头。4 字节标头限制为 2Gb。
asn1 | cdr | sunrm | fcgi | tpkt | line
- 这些包类型仅在接收时有效。在发送包时,应用程序负责提供正确的标头。但是,在接收时,会为接收到的每个完整包向控制进程发送一条消息,并且类似地,每次调用gen_tcp:recv/2,3
都会返回一个完整的包。不会删除标头。包类型的含义如下
asn1
- ASN.1 BERsunrm
- Sun 的 RPC 编码cdr
- CORBA (GIOP 1.1)fcgi
- Fast CGItpkt
- 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
。但是,在某些情况下它们可能很有用,例如解析分块编码中的 trailers。
{packet_size, Integer}
(TCP/IP 套接字) - 设置包体的最大允许长度。如果包头指示包的长度长于最大允许长度,则该包被视为无效。如果包头对于套接字接收缓冲区来说太大,也会发生同样的情况。对于面向行的协议 (
line
,http*
),packet_size
选项还可以保证接受长度达到指定长度的行,并且不会因为内部缓冲区限制而被视为无效。{line_delimiter, Char}
(TCP/IP 套接字) - 为面向行的协议 (line
) 设置行分隔符字符。默认为$\n
。{raw, Protocol, OptionNum, ValueBin}
- 请参见下文。{read_ahead, Boolean}
- 如果设置为false
,则避免从 OS 套接字层提前读取。此选项的默认值为true
,这会加快包头解析。设置false
会带来性能损失,因为必须先读取包头,才能确切知道要为包体读取多少字节,这大致会使读取操作的数量加倍。例如,在切换到 kTLS 之前,此选项的使用至关重要,ktls 通过设置特殊的(原始)套接字选项来激活 OS 套接字层的加密和解密。因此,如果 Erlang 套接字层已提前读取,则它已读取了 OS 套接字层要解密的字节,这会导致连接的包解密失败。
警告
对于包头中包长度不在固定位置的包模式,例如
line
或asn1
,不提前读取可能会变得非常低效,因为有时实现此目的的唯一方法是一次读取一个字节,直到找到长度或包结尾。{read_packets, Integer}
(UDP 套接字) - 设置在有数据可用时,无需套接字干预即可读取的最大 UDP 包数。当已读取并将这些数量的包传递到目标进程后,在收到有关可用数据的新通知之前,不会读取新包。默认为5
。如果此参数设置得过高,则系统可能会因为 UDP 包泛滥而变得无响应。{recbuf, Size}
- 套接字要使用的最小接收缓冲区大小。我们建议您使用getopts/2
来检索操作系统设置的大小。{recvtclass, Boolean}
- 如果设置为true
,则在实现协议IPPROTO_IPV6
选项IPV6_RECVTCLASS
或套接字的IPV6_2292RECVTCLASS
的平台上激活返回接收到的TCLASS
值。无论平台返回IPV6_TCLASS
还是IPV6_RECVTCLASS
CMSG 值,该值都将作为{tclass,TCLASS}
元组返回。对于支持使用有效负载数据接收辅助数据的面向包的套接字(
gen_udp
和gen_sctp
),TCLASS
值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp
),获取TCLASS
值的唯一方法是平台是否支持pktoptions
选项。{recvtos, Boolean}
- 如果设置为true
,则在实现协议IPPROTO_IP
选项IP_RECVTOS
的平台上激活返回接收到的TOS
值。无论平台返回IP_TOS
还是IP_RECVTOS
CMSG 值,该值都将作为{tos,TOS}
元组返回。对于支持使用有效负载数据接收辅助数据的面向包的套接字(
gen_udp
和gen_sctp
),TOS
值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp
),获取TOS
值的唯一方法是平台是否支持pktoptions
选项。{recvttl, Boolean}
- 如果设置为true
,则在实现协议IPPROTO_IP
选项IP_RECVTTL
的平台上激活返回接收到的TTL
值。无论平台返回IP_TTL
还是IP_RECVTTL
CMSG 值,该值都将作为{ttl,TTL}
元组返回。对于支持使用有效负载数据接收辅助数据的面向包的套接字(
gen_udp
和gen_sctp
),TTL
值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp
),获取TTL
值的唯一方法是平台是否支持pktoptions
选项。{reuseaddr, Boolean}
- 允许或禁止重用本地地址。默认情况下,禁止重用。注意
在 Windows 上,除非同时设置
{reuseport, true}
,否则{reuseaddr, true}
将不起作用。如果两者都设置,则会启用SO_REUSEADDR
Windows 套接字选项。这是因为在 Windows 上设置SO_REUSEADDR
大致与在 BSD 上同时设置SO_REUSEADDR
和SO_REUSEPORT
具有相同的行为。此行为是在 OTP 26.0 中引入的。变更
Windows 上的先前行为
- 在 OTP 25.0 之前,
{reuseaddr, true}
选项会被静默忽略。 - 在 OTP 25.0 到 OTP 25.2 的前身版本之间,如果设置了
{reuseaddr, true}
,则会设置底层的SO_REUSEADDR
套接字选项。 - 在 OTP 25.2 到 OTP 26.0 的前身版本之间,只有在 UDP 套接字上设置了
{reuseaddr, true}
时,才会设置底层的SO_REUSEADDR
套接字选项,在其他套接字上则会被静默忽略。
另请参阅
exclusiveaddruse
选项。- 在 OTP 25.0 之前,
{reuseport, Boolean}
- 允许或禁止重用本地端口,这可能会或可能不会根据底层操作系统进行负载均衡。默认情况下,禁止重用。另请参阅reuseport_lb
。注意
在 Windows 上,除非同时设置
{reuseaddr, true}
,否则{reuseport, true}
将不起作用。如果两者都设置,则会启用SO_REUSEADDR
Windows 套接字选项。这是因为在 Windows 上设置SO_REUSEADDR
大致与在 BSD 上同时设置SO_REUSEADDR
和SO_REUSEPORT
具有相同的行为。reuseport
选项是在 OTP 26.0 中引入的。另请参阅
exclusiveaddruse
选项。注意
reuseport
可能与reuseport_lb
底层的选项相同,也可能不相同,具体取决于底层操作系统。例如,在 Linux 上它们是相同的。当它们是相同的底层选项时,同时操作它们可能会导致意想不到的相互影响。例如,通过启用reuseport
,然后禁用reuseport_lb
,最终两者都将被禁用。注意
此选项当前不支持使用
inet_backend = socket
创建的套接字{reuseport_lb, Boolean}
- 允许或禁止重用本地端口并进行负载均衡。默认情况下,禁止重用。另请参阅reuseport
。注意
reuseport_lb
可能与reuseport
底层的选项相同,也可能不相同,具体取决于底层操作系统。例如,在 Linux 上它们是相同的。当它们是相同的底层选项时,同时操作它们可能会导致意想不到的相互影响。例如,通过启用reuseport_lb
,然后禁用reuseport
,最终两者都将被禁用。注意
此选项当前不支持使用
inet_backend = socket
创建的套接字{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 套接字) - 当此选项设置为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
级别选项。不同系统之间的行为和允许范围有所不同。在未实现此选项的平台上,此选项将被忽略。谨慎使用。{tclass, Integer}
- 在实现此选项的平台上设置IPV6_TCLASS IP
级别选项。不同系统之间的行为和允许范围有所不同。在未实现此选项的平台上,此选项将被忽略。谨慎使用。
除了这些选项外,还可以使用原始选项规范。原始选项指定为四元组,以标签 raw
开头,后跟协议级别、选项编号和指定为二进制的选项值。这对应于 C 套接字 API 中 setsockopt
调用的第二个、第三个和第四个参数。选项值必须以平台的本机字节序编码,如果需要结构,则必须遵循特定平台上的结构对齐约定。
使用原始套接字选项需要详细了解当前操作系统和 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}]),
诸如此类的代码本质上是不可移植的,即使同一平台上同一操作系统的不同版本对此类选项操作的响应也可能不同。请谨慎使用。
请注意,可以使用本手册页开头提到的内核配置参数更改 TCP/IP 套接字的默认选项。
-spec sockname(Socket :: socket()) -> {ok, {ip_address(), port_number()} | returned_non_ip_address()} | {error, posix()}.
返回套接字的本地地址和端口号。
请注意,对于 SCTP 套接字,此函数仅返回其中一个套接字地址。函数 socknames/1,2
返回所有地址。
-spec socknames(Socket :: socket()) -> {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.
等同于 socknames(Socket, 0)
。
-spec socknames(Socket, Assoc) -> {ok, [{Address, Port}]} | {error, posix()} when Socket :: socket(), Assoc :: #sctp_assoc_change{state :: term(), error :: term(), outbound_streams :: term(), inbound_streams :: term(), assoc_id :: term()} | gen_sctp:assoc_id(), Address :: ip_address(), Port :: non_neg_integer().
返回套接字的所有本地地址。
返回指定关联 Assoc
的套接字的所有本地地址/端口号对的列表。
此函数可以为多宿主套接字(例如 SCTP 套接字)返回多个地址。对于其他套接字,它返回一个单元素列表。
请注意,根据 SCTP Sockets API Extensions 的定义,对于一对一风格的套接字,参数 Assoc
将被忽略。对于一对多风格的套接字,特殊值 0
定义为表示返回的地址必须没有任何特定的关联。不同的 SCTP 实现对此的解释略有不同。