查看源代码 inet (内核 v10.2)

访问网络协议。

此模块与 gen_tcpgen_udpgen_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 - 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 - 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 - 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 - EREFUSED
  • eremchg - 远程地址已更改
  • eremdev - 远程设备
  • eremote - 路径名命中远程文件系统
  • eremoteio - 远程 I/O 错误
  • eremoterelease - EREMOTERELEASE
  • erofs - 只读文件系统
  • erpcmismatch - 错误的 RPC 版本
  • erremote - 对象是远程的
  • eshutdown - 套接字关闭后无法发送
  • esocktnosupport - 不支持的套接字类型
  • espipe - 无效的查找
  • esrch - 没有这样的进程
  • esrmnt - Srmount 错误
  • estale - 过时的远程文件句柄
  • esuccess - 错误 0
  • etime - 计时器已过期
  • etimedout - 连接超时
  • etoomanyrefs - 引用过多
  • etxtbsy - 文本文件或伪设备忙
  • euclean - 结构需要清理
  • eunatch - 未附加协议驱动程序
  • eusers - 用户过多
  • eversion - 版本不匹配
  • ewouldblock - 操作将阻塞
  • exdev - 跨设备链接
  • exfull - 消息表已满
  • nxdomain - 找不到主机名或域名

概要

类型:导出的数据类型

辅助数据/控制消息。

通用网络地址。

一个描述主机的记录;包括名称和地址。

socket/0 的实现后端选择器。

local 族(AF_LOCAL | AF_UNIX)的网络地址

POSIX 错误代码 atom/0

非 IP 网络地址。

此模块及其兄弟模块识别的套接字。

类型:内部数据类型

接口地址描述列表。

inet6 族(AF_INET6,IPv6)的网络地址

inet 族(AF_INET,IPv4)的网络地址

类型

用于选择统计项目的选项。

函数

取消套接字监视器。

关闭任何类型的套接字。

将错误代码格式化为 string/0

获取 inet 配置。

在特定地址族中将主机解析为地址。

在特定地址族中将主机解析为地址列表。

将地址解析(反向)为 #hostent{} 记录。

将主机名解析为 #hostent{} 记录。

在特定地址族中将主机名解析为 #hostent{} 记录。

获取本地主机名。

获取接口名称和地址。

在特定命名空间中获取接口名称和地址。

获取套接字的一个或多个选项。

等同于 getstat/2

获取套接字的一个或多个统计信息选项。

i()

等同于 tcpudpsctp 协议的 i/1

i/1

列出网络套接字。

i/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.
-type ancillary_data() :: [{tos, byte()} | {tclass, byte()} | {ttl, byte()}].

辅助数据/控制消息。

与数据包一起接收的辅助数据,从 TCP 套接字使用套接字选项 pktoptions 读取,或在调用 gen_udp:send/4gen_udp:send/5 时设置。

这些值对应于当前活动的套接字 选项 recvtosrecvtclassrecvttl,或者对于单个发送操作,对应于覆盖当前活动套接字选项的选项。

-type family_address() :: inet_address() | inet6_address() | local_address().

通用网络地址。

形式为 {Family, Destination} 的通用网络地址格式,其中 Family 是一个原子,例如 localDestination 的格式取决于 FamilyDestination 是一个完整的地址(例如,带有端口号的 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 hostname() :: atom() | string().
-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().
-type local_address() :: {local, File :: binary() | string()}.

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 错误代码 部分。

链接到此类型

returned_non_ip_address()

查看源代码
-type returned_non_ip_address() :: {local, binary()} | {unspec, <<>>} | {undefined, any()}.

非 IP 网络地址。

从套接字 API 函数返回的除了 ip_address/0 之外的地址。特别参见 local_address/0unspec 族对应于 AF_UNSPEC,如果另一侧没有套接字地址,则可能出现。undefined 族只能在虚拟机无法识别地址族的极不可能情况下出现。

-type socket() :: port() | module_socket().

此模块及其兄弟模块识别的套接字。

请参阅 gen_tcp:socket/0gen_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_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.

类型:内部数据类型

链接到此类型

getifaddrs_ifopts()

查看源代码 (未导出)
-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,_}
  • 此后紧接着,如果 broadcastFlags 的成员,则可能跟随 {broadaddr,_},如果 pointtopointFlags 的成员,则可能跟随 {dstaddr,_}。对于相同的 {addr,_}{dstaddr,_}{broadaddr,_} 都不会出现。
  • 跟随 {addr,Addr} 元组的任何 {netmask,_}{broadaddr,_}{dstaddr,_} 元组都与地址 Addr 相关。

在 Solaris 上不返回元组 {hwaddr,_},因为硬件地址历史上属于链路层,并且 Solaris API 函数 getaddrinfo() 不返回它。

警告

在 Windows 上,数据是从不同的 OS API 函数中获取的,因此 NetmaskBroadaddr 值可以计算得出,就像一些 Flags 值一样。

链接到此类型

inet6_address()

查看源代码 (未导出)
-type inet6_address() :: {inet6, {ip6_address() | any | loopback, port_number()}}.

inet6 族(AF_INET6,IPv6)的网络地址

警告

此地址格式目前是实验性的,为了完整性,使所有地址族都有一个 {Family, Destination} 表示。

链接到此类型

inet_address()

查看源代码 (未导出)
-type inet_address() :: {inet, {ip4_address() | any | loopback, port_number()}}.

inet 族(AF_INET,IPv4)的网络地址

警告

此地址格式目前是实验性的,为了完整性,使所有地址族都有一个 {Family, Destination} 表示。

类型

链接到此类型

ether_address()

查看源代码 (未导出)
-type ether_address() :: [0..255].
链接到此类型

i_option()

查看源代码 (未导出)
-type i_option() ::
          port | module | recv | sent | owner | local_address |
          {local_address, ShowPorts :: boolean()} |
          foreign_address |
          {foreign_address, ShowPorts :: boolean()} |
          state | type.

用于选择统计项目的选项。

关于 ShowPorts,请参阅 i/2 函数中描述的 show_ports,默认为 false

链接到此类型

module_socket()

查看源代码 (未导出)
-type module_socket() :: {'$inet', Handler :: module(), Handle :: term()}.

函数

链接到此函数

cancel_monitor(MRef)

查看源代码 (自 OTP 24.0 起)
-spec cancel_monitor(MRef) -> boolean() when MRef :: reference().

取消套接字监视器。

如果 MRef 是调用进程通过调用 monitor/1 获取的引用,则此监视器将被移除。如果监视器已被移除,则不会发生任何事情。

返回的值是以下之一

  • true - 找到了监视器并已将其移除。在这种情况下,尚未传递与此监视器对应的 'DOWN' 消息,并且不会传递。

  • false - 未找到监视器,无法将其移除。可能因为监视器已触发,并且在调用者消息队列中存在相应的 'DOWN' 消息。

-spec close(Socket) -> ok when Socket :: socket().

关闭任何类型的套接字。

-spec format_error(Reason) -> string() when Reason :: posix() | system_limit.

将错误代码格式化为 string/0

返回诊断错误字符串。有关可能的 POSIX 值和相应的字符串,请参阅 POSIX 错误代码部分。

-spec get_rc() -> [{Par :: atom(), Val :: any()} | {Par :: atom(), Val1 :: any(), Val2 :: any()}].

获取 inet 配置。

以记录的配置参数列表的形式返回 inet 配置数据库的状态。有关更多信息,请参阅 ERTS 用户指南:Inet 配置

仅返回具有非默认值的实际参数,例如,不返回指定配置参数其他来源的指令,也不返回清除参数的指令。

-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()}
                 when
                     Host :: ip_address() | hostname(),
                     Family :: address_family(),
                     Address :: ip_address().

在特定地址族中将主机解析为地址。

返回 HostIP 地址,形式为整数元组。Host 可以是 IP 地址、单个 hostname/0 或完全限定的 hostname/0

链接到此函数

getaddrs(Host, Family)

查看源代码
-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

链接到此函数

gethostbyaddr(Address)

查看源代码
-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()}
                       when Address :: string() | ip_address(), Hostent :: hostent().

将地址解析(反向)为 #hostent{} 记录。

返回具有指定地址的主机的 #hostent{} 记录。

链接到此函数

gethostbyname(Hostname)

查看源代码
-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()}
                       when Hostname :: hostname(), Hostent :: hostent().

将主机名解析为 #hostent{} 记录。

返回具有指定 Hostname 的主机的 #hostent{} 记录。

此函数使用解析器,通常是本机 (OS) 解析器。

如果解析器选项 inet6true,则会查找 IPv6 地址。

有关解析器配置的信息,请参阅 ERTS 用户指南:Inet 配置

许多解析器的一个怪癖是将整数字符串解释为 IP 地址。例如,整数字符串 "3232235521" 和字符串 "192.168.0.1" 都被转换为 IP 地址 {192,168,0,1}

链接到此函数

gethostbyname(Hostname, Family)

查看源代码
-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().

获取本地主机名。

返回本地主机名。永远不会失败。

链接到此函数

getifaddrs()

查看源代码 (自 OTP R14B01 起)
-spec getifaddrs() -> {ok, [{Ifname :: string(), Ifopts :: getifaddrs_ifopts()}]} | {error, posix()}.

获取接口名称和地址。

返回包含接口名称和接口地址的 2 元组列表。Ifname 是 Unicode 字符串,Ifopts 是接口地址描述元组的列表。

接口地址描述元组记录在 Ifopts 值的类型下。

链接到此函数

getifaddrs/1

查看源代码 (自 OTP 21.2 起)
-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}

链接到此函数

getopts(Socket, Options)

查看源代码
-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

链接到此函数

getstat(Socket, Options)

查看源代码
-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 - 从套接字发送的字节数。

链接到此函数

i()

查看源代码 (自 OTP 21.0 起)
-spec i() -> ok.

等同于 tcpudpsctp 协议的 i/1

链接到此函数

i/1

查看源代码 (自 OTP 21.0 起)
-spec i(show_ports | socket_protocol() | [i_option()]) -> ok.

列出网络套接字。

对于参数 Proto,等效于 i(Proto, Options),其中 Optionsi_option/0 中的所有 atom/0 的列表。

对于参数 Options,等效于 `i(Proto, Options),其中 Prototcpudpsctp。对于参数 show_ports (自 OTP 27.0 起),等效于 `i(Proto, Options),其中 Optioni_option/0 中所有选项的列表,其中 ShowPorts = true

链接到此函数

i/2

查看源代码 (自 OTP 21.0 起)
-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' 的端口号)转换为服务名称。
链接到此函数

info(Socket)

查看源代码 (自 OTP 24.0 起)
-spec info(Socket) -> Info when Socket :: socket(), Info :: term().

获取有关套接字的信息。

返回一个包含关于套接字的杂项信息的项。

链接到此函数

ipv4_mapped_ipv6_address/1

查看源代码 (自 OTP 21.0 起)
-spec ipv4_mapped_ipv6_address(ip_address()) -> ip_address().

在 IPv4 地址和 IPv4 映射的 IPv6 地址之间转换。

将 IPv4 地址转换为 IPv4 映射的 IPv6 地址,反之亦然。当从 IPv6 地址转换时,除了低 2 个字之外的所有字都会被忽略,因此此函数也适用于某些其他类型的 IPv6 地址,而不是 IPv4 映射的地址。

链接到此函数

is_ip_address(IPAddress)

查看源代码 (自 OTP 25.0 起)
-spec is_ip_address(IPAddress) -> boolean() when IPAddress :: ip_address() | term().

测试是否为 IP 地址。

测试参数 IPAddress 是否为 ip_address/0,如果是,则返回 true,否则返回 false

链接到此函数

is_ipv4_address(IPv4Address)

查看源代码 (自 OTP 25.0 起)
-spec is_ipv4_address(IPv4Address) -> boolean() when IPv4Address :: ip4_address() | term().

测试是否为 IPv4 地址。

测试参数 IPv4Address 是否为 ip4_address/0,如果是,则返回 true,否则返回 false

链接到此函数

is_ipv6_address(IPv6Address)

查看源代码 (自 OTP 25.0 起)
-spec is_ipv6_address(IPv6Address) -> boolean() when IPv6Address :: ip6_address() | term().

测试是否为 IPv6 地址。

测试参数 IPv6Address 是否为 ip6_address/0,如果是,则返回 true,否则返回 false

链接到此函数

monitor(Socket)

查看源代码 (自 OTP 24.0 起)
-spec monitor(Socket) -> reference() when Socket :: socket().

启动套接字监视器。

如果要监视的 Socket 不存在,或者当监视器被触发时,将发送一个具有以下模式的 'DOWN' 消息

	    {'DOWN', MonitorRef, Type, Object, Info}
  • MonitorRef - 此函数的返回值。

  • Type - 套接字的类型,可以是以下 atom/0 之一:portsocket

  • Object - 被监视的实体,即触发事件的套接字。

  • Info - 套接字的终止原因或 nosock(调用此函数时 Socket 不存在)。

多次调用同一个 Socketinet:monitor/1 不是错误;每次调用都会创建一个监视器。

当套接字以任何方式关闭时,例如 API 调用、远程端关闭、所有者退出时由信号关闭等,都会触发监视器。

链接到此函数

ntoa(IpAddress)

查看源代码 (自 OTP R16B02 起)
-spec ntoa(IpAddress) -> Address | {error, einval} when Address :: string(), IpAddress :: ip_address().

ip_address/0 解析为 IPv4 或 IPv6 地址字符串。

链接到此函数

parse_address(Address)

查看源代码 (自 OTP R16B 起)
-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

链接到此函数

parse_ipv4_address(Address)

查看源代码 (自 OTP R16B 起)
-spec parse_ipv4_address(Address) -> {ok, IPv4Address} | {error, einval}
                            when Address :: string(), IPv4Address :: ip4_address().

将(宽松的)IPv4 地址字符串解析为 ip4_address/0

接受简短形式的 IPv4 地址字符串(少于 4 个字段),例如 "127.1""0x7f000001"

链接到此函数

parse_ipv4strict_address(Address)

查看源代码 (自 OTP R16B 起)
-spec parse_ipv4strict_address(Address) -> {ok, IPv4Address} | {error, einval}
                                  when Address :: string(), IPv4Address :: ip4_address().

将 IPv4 地址字符串解析为 ip4_address/0

需要包含四个字段的 IPv4 地址字符串,即:不是简短形式的地址字符串。

链接到此函数

parse_ipv6_address(Address)

查看源代码 (自 OTP R16B 起)
-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 地址。

链接到此函数

parse_ipv6strict_address(Address)

查看源代码 (自 OTP R16B 起)
-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" 相同)。

链接到此函数

parse_strict_address(Address)

查看源代码 (自 OTP R16B 起)
-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 返回所有地址。

链接到此函数

peernames(Socket)

查看源代码 (自 OTP R16B03 起)
-spec peernames(Socket :: socket()) ->
                   {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.

等同于 peernames(Socket, 0)

请注意,此函数对于 SCTP 一对多样式套接字的行为未由 SCTP 套接字 API 扩展定义。

链接到此函数

peernames(Socket, Assoc)

查看源代码 (自 OTP R16B03 起)
-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 套接字)返回多个地址。对于其他套接字,它返回一个单元素列表。

请注意,参数 AssocSCTP 套接字 API 扩展 定义为对一对一样式套接字忽略。特殊值 0 的含义不幸地未定义,因此对于一对多样式套接字的行为也是如此。

-spec port(Socket) -> {ok, Port} | {error, any()} when Socket :: socket(), Port :: port_number().

返回套接字的本地端口号。

链接到此函数

setopts(Socket, Options)

查看源代码
-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,3gen_udp:recv/2,3gen_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 的值设置为适合应用程序的值来提供流控制。另一方不能比接收方读取的速度更快地发送数据。

  • {broadcast, Boolean} (UDP 套接字) - 启用/禁用发送广播的权限。

  • {buffer, Size} - 驱动程序使用的用户级缓冲区的大小。不要与对应于内核套接字缓冲区的 sndbufrecbuf 选项混淆。对于 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_watermarkhigh_watermarklow_watermark

    请注意,分发套接字禁用 high_msgq_watermarklow_msgq_watermark 的使用。而是使用 分发缓冲区繁忙限制,这是一个类似的功能。

  • {high_watermark, Size} (TCP/IP 套接字) - 当 ERTS 套接字实现内部排队的数据量达到此限制时,套接字将设置为繁忙状态。默认为 8 kB。

    如果套接字消息队列繁忙或套接字本身繁忙,则向套接字发送数据的发送方会被暂停。

    有关更多信息,请参阅选项 low_watermarkhigh_msgq_watermarklow_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_watermarkhigh_watermarklow_watermark

    请注意,分发套接字禁用 high_msgq_watermarklow_msgq_watermark 的使用。相反,它们使用 分发缓冲区繁忙限制,这是一个类似的功能。

  • {low_watermark, Size} (TCP/IP 套接字) - 如果套接字处于繁忙状态,则当 ERTS 套接字实现内部排队的数据量低于此限制时,套接字将设置为非繁忙状态。默认为 4 kB。

    由于繁忙消息队列或繁忙套接字而暂停的发送方将在套接字消息队列和套接字不繁忙时恢复。

    有关更多信息,请参阅选项 high_watermarkhigh_msgq_watermarklow_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,4gen_tcp:listen/2gen_udp:open/1,2gen_sctp:open/0,1,2,以及 getifaddrs/1

    此选项使用 Linux 特定的系统调用 setns(),例如 Linux 内核 3.0 或更高版本,因此仅当为这种操作系统编译运行时系统时才存在。

    虚拟机还需要提升的权限,要么以超级用户身份运行,要么(对于 Linux)根据 setns(2) 的文档,拥有 CAP_SYS_ADMIN 能力。然而,在测试过程中,还证明了 CAP_SYS_PTRACECAP_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,4gen_tcp:listen/2gen_udp:open/1,2gen_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 BER
      • sunrm - Sun 的 RPC 编码
      • cdr - CORBA (GIOP 1.1)
      • fcgi - Fast 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。但是,在某些情况下它们可能很有用,例如解析分块编码中的 trailers。

  • {packet_size, Integer}(TCP/IP 套接字) - 设置包体的最大允许长度。如果包头指示包的长度长于最大允许长度,则该包被视为无效。如果包头对于套接字接收缓冲区来说太大,也会发生同样的情况。

    对于面向行的协议 (linehttp*),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 套接字层要解密的字节,这会导致连接的包解密失败。

    警告

    对于包头中包长度不在固定位置的包模式,例如 lineasn1,不提前读取可能会变得非常低效,因为有时实现此目的的唯一方法是一次读取一个字节,直到找到长度或包结尾。

  • {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_udpgen_sctp),TCLASS 值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp),获取 TCLASS 值的唯一方法是平台是否支持 pktoptions 选项。

  • {recvtos, Boolean} - 如果设置为 true,则在实现协议 IPPROTO_IP 选项 IP_RECVTOS 的平台上激活返回接收到的 TOS 值。无论平台返回 IP_TOS 还是 IP_RECVTOS CMSG 值,该值都将作为 {tos,TOS} 元组返回。

    对于支持使用有效负载数据接收辅助数据的面向包的套接字(gen_udpgen_sctp),TOS 值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp),获取 TOS 值的唯一方法是平台是否支持 pktoptions 选项。

  • {recvttl, Boolean} - 如果设置为 true,则在实现协议 IPPROTO_IP 选项 IP_RECVTTL 的平台上激活返回接收到的 TTL 值。无论平台返回 IP_TTL 还是 IP_RECVTTL CMSG 值,该值都将作为 {ttl,TTL} 元组返回。

    对于支持使用有效负载数据接收辅助数据的面向包的套接字(gen_udpgen_sctp),TTL 值在 辅助数据列表中包含的扩展返回元组中返回。对于面向流的套接字 (gen_tcp),获取 TTL 值的唯一方法是平台是否支持 pktoptions 选项。

  • {reuseaddr, Boolean} - 允许或禁止重用本地地址。默认情况下,禁止重用。

    注意

    在 Windows 上,除非同时设置 {reuseport, true},否则 {reuseaddr, true} 将不起作用。如果两者都设置,则会启用 SO_REUSEADDR Windows 套接字选项。这是因为在 Windows 上设置 SO_REUSEADDR 大致与在 BSD 上同时设置 SO_REUSEADDRSO_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 选项。

  • {reuseport, Boolean} - 允许或禁止重用本地端口,这可能会或可能不会根据底层操作系统进行负载均衡。默认情况下,禁止重用。另请参阅 reuseport_lb

    注意

    在 Windows 上,除非同时设置 {reuseaddr, true},否则 {reuseport, true} 将不起作用。如果两者都设置,则会启用 SO_REUSEADDR Windows 套接字选项。这是因为在 Windows 上设置 SO_REUSEADDR 大致与在 BSD 上同时设置 SO_REUSEADDRSO_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 返回所有地址。

链接到此函数

socknames(Socket)

查看源代码 (自 OTP R16B03 起)
-spec socknames(Socket :: socket()) ->
                   {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.

等同于 socknames(Socket, 0)

链接到此函数

socknames(Socket, Assoc)

查看源代码 (自 OTP R16B03 起)
-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 实现对此的解释略有不同。