檢視原始碼 inet (核心 v10.2)
存取網路協定。
此模組與 gen_tcp
、gen_udp
和 gen_sctp
一起提供對 IP 上 TCP、SCTP 和 UDP 網路協定的存取,以及本機(unix)位址域/協定域上的串流和資料包協定。
另請參閱 ERTS 使用者指南:Inet 設定,以了解如何為 IP 通訊設定 Erlang 執行時系統的更多資訊。
以下兩個核心組態參數會影響在 Erlang 節點上開啟的所有 gen_tcp
socket 的行為
inet_default_connect_options
可以包含用於gen_tcp:connect/2,3,4
](gen_tcp:connect/2
) 呼叫建立的所有 socket 的預設選項列表。inet_default_listen_options
可以包含用於gen_tcp:listen/2
呼叫建立的 socket 的預設選項列表。
對於 gen_tcp:accept/1,2
呼叫,會繼承監聽 socket 的選項值。因此,對於 accept
沒有對應的應用程式變數。
使用上面的核心組態參數,可以為節點上的所有 TCP socket 設定預設選項,但請謹慎使用。例如,可以透過這種方式指定 {delay_send,true}
之類的選項。以下是一個啟動 Erlang 節點的範例,其中所有 socket 都使用延遲發送
$ 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
- 強制掛載一個髒的 fsedom
- 數學引數超出範圍edotdot
- 跨掛載點edquot
- 超出磁碟配額eduppkg
- 重複的套件名稱eexist
- 檔案已存在efault
- 系統呼叫引數中的錯誤位址efbig
- 檔案太大ehostdown
- 主機關閉ehostunreach
- 無法連線到主機eidrm
- 識別碼已移除einit
- 初始化錯誤einprogress
- 操作正在進行中eintr
- 系統呼叫被中斷einval
- 無效的引數eio
- I/O 錯誤eisconn
- Socket 已連線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
- Socket 未連線enotdir
- 不是目錄enotempty
- 目錄不是空的enotnam
- 不是具名檔案enotsock
- 在非 socket 上進行 socket 操作enotsup
- 不支援操作enotty
-ioctl
的不當裝置enotuniq
- 網路上名稱不是唯一的enxio
- 沒有此裝置或位址eopnotsupp
- Socket 上不支援操作eperm
- 不是擁有者epfnosupport
- 不支援協定族epipe
- 管道已損毀eproclim
- 程序太多eprocunavail
- 程序的錯誤程序eprogmismatch
- 錯誤的程式版本eprogunavail
- RPC 程式無法使用eproto
- 協定錯誤eprotonosupport
- 不支援協定eprototype
- Socket 的錯誤協定類型erange
- 數學結果無法表示erefused
- EREFUSEDeremchg
- 遠端位址已變更eremdev
- 遠端裝置eremote
- 路徑名稱命中遠端檔案系統eremoteio
- 遠端 I/O 錯誤eremoterelease
- EREMOTERELEASEerofs
- 唯讀檔案系統erpcmismatch
- 錯誤的 RPC 版本erremote
- 物件是遠端的eshutdown
- 無法在 socket 關閉後傳送esocktnosupport
- 不支援 Socket 類型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 網路位址。
此模組及其同級模組可識別的 socket。
函式
取消 socket 監控。
關閉任何類型的 socket。
將錯誤碼格式化為 string/0
。
取得 inet
配置。
在特定的位址系列中,將主機解析為位址。
在特定的位址系列中,將主機解析為位址列表。
將位址(反向)解析為 #hostent{}
記錄。
將主機名稱解析為 #hostent{}
記錄。
在特定的位址系列中,將主機名稱解析為 #hostent{}
記錄。
取得本機主機名稱。
取得介面名稱和位址。
在特定的命名空間中,取得介面名稱和位址。
取得 socket 的一個或多個選項。
等同於 getstat/2
。
取得 socket 的一個或多個統計選項。
列出網路 socket。
列出網路 socket。
取得關於 socket 的資訊。
在 IPv4 位址和 IPv4 對應的 IPv6 位址之間轉換。
測試是否為 IP 位址。
測試是否為 IPv4 位址。
測試是否為 IPv6 位址。
啟動 socket 監控。
將 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
。
傳回 socket 遠端的位址。
傳回 socket 所有遠端的位址。
傳回 socket 的本機埠號。
設定 socket 的一個或多個選項。
傳回 socket 的本機位址和埠號。
傳回 socket 的所有本機位址。
類型:匯出的資料類型
-type address_family() :: inet | inet6 | local.
輔助資料 / 控制訊息。
與資料封包一起收到的輔助資料,使用 TCP socket 的 socket 選項 pktoptions
讀取,或在呼叫 gen_udp:send/4
或 gen_udp:send/5
時設定。
這些值對應於目前啟用的 socket 選項 recvtos
、recvtclass
和 recvttl
,或是單次傳送操作覆寫目前啟用 socket 選項的選項。
-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](socket/0
) 選擇實作後端。目前的預設值是 inet
,它使用 inet_drv.c
來呼叫平台的 socket 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 網域 socket」,僅適用於類 Unix 系統。
File
通常是本機檔案系統中的檔案路徑名稱。它的長度受作業系統限制,傳統上為 108 個位元組。
binary/0
會按原樣傳遞至作業系統,但 string/0
會根據 系統檔案名稱編碼模式進行編碼。
也可能存在其他位址,例如,Linux 實作「抽象位址」。請參閱您系統上關於 Unix 網域 Socket 的文件,通常是手冊第 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 網路位址。
除了從 socket API 函式傳回的 ip_address/0
之外的位址。特別請參閱 local_address/0
。 unspec
系列對應於 AF_UNSPEC
,如果另一方沒有 socket 位址,則可能會發生。undefined
系列只會在虛擬機器無法辨識位址系列的罕見情況下發生。
-type socket() :: port() | module_socket().
此模組及其同級模組可識別的 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,_}
。{dstaddr,_}
和{broadaddr,_}
不會針對相同的{addr,_}
出現。 - 任何緊接在
{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}
表示法。
類型
函數
取消 socket 監控。
如果 MRef
是呼叫進程透過呼叫 monitor/1
取得的參考,則會移除此監視器。如果監視器已移除,則不會發生任何事。
傳回值為下列其中之一:
true
- 找到並移除了監視器。在這種情況下,沒有傳送對應於此監視器的'DOWN'
訊息,而且也不會傳送。false
- 未找到監視器,且無法移除。可能是因為監視器已觸發,且在呼叫者的訊息佇列中有對應的'DOWN'
訊息。
-spec close(Socket) -> ok when Socket :: 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
下的 socket 選項 {netns, Namespace}
。
-spec getopts(Socket, Options) -> {ok, OptionValues} | {error, posix()} when Socket :: socket(), Options :: [socket_getopt()], OptionValues :: [socket_optval()].
取得 socket 的一個或多個選項。
從 Socket
取得 Options
列表中所有選項。如需可用選項的列表,請參閱 setopts/2
。另請參閱 socket_optval()
引用的協定特定類型的描述。
傳回的 OptionValues
列表中元素的數量不一定與要求的選項數量相對應。如果作業系統無法支援某個選項,則會將其從傳回的列表中省略。只有在無法取得 socket 選項時才會傳回錯誤元組(也就是說,socket 已關閉或原始請求中的緩衝區大小過大)。此行為是為了保持回溯相容性。
原始選項請求 RawOptReq = {raw, Protocol, OptionNum, ValueSpec}
可以用於取得模擬器未(明確)支援的 socket 選項資訊。使用原始 socket 選項會使程式碼不具可攜性,但允許 Erlang 程式設計人員利用特定平台上存在的不尋常功能。
RawOptReq
由標記 raw
後接協定層級、選項編號,以及二進位或儲存選項值的緩衝區大小(以位元組為單位)組成。當底層 getsockopt
需要引數欄位中的輸入時,應使用二進位。在這種情況下,二進位大小應與傳回值所需的緩衝區大小相對應。RawOptReq
中提供的值對應於 C socket API 中 getsockopt
呼叫的第二、第三和第四/第五個參數。儲存在緩衝區中的值會以二進位 ValueBin
的形式傳回,其中所有值都以原生位元組順序編碼。
請求和檢查原始 socket 選項需要有關目前作業系統和 TCP 堆疊的低階資訊。
範例
考慮一部 Linux 機器,其中選項 TCP_INFO
可用於收集 socket 的 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()}].
取得 socket 的一個或多個統計選項。
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
- socket 收到的封包平均大小(以位元組為單位)。recv_cnt
- socket 收到的封包數量。recv_dvi
- socket 收到的封包平均大小偏差(以位元組為單位)。recv_max
- socket 收到的最大封包大小(以位元組為單位)。recv_oct
- socket 收到的位元組數量。send_avg
- 從 socket 送出的封包平均大小(以位元組為單位)。send_cnt
- 從 socket 送出的封包數量。send_pend
- 等待由 socket 送出的位元組數量。send_max
- 從 socket 送出的最大封包大小(以位元組為單位)。send_oct
- 從 socket 送出的位元組數量。
-spec i() -> ok.
對於協定 tcp
、udp
和 sctp
,等同於 i/1
。
-spec i(show_ports | socket_protocol() | [i_option()]) -> ok.
列出網路 socket。
使用與 i(Proto, Options)
等效的引數 Proto
,其中 Options
是 i_option/0
中所有 atom/0
的列表。
使用引數 Options
,對於 Proto
:tcp
、udp
和 sctp
,等同於 `i(Proto, Options)。使用引數 show_ports
(自 OTP 27.0 起),等同於 `i(Proto, Options),其中 Option
是 i_option/0
中所有選項的列表,且 ShowPorts = true
。
-spec i(socket_protocol(), show_ports | (Options :: [i_option()])) -> ok.
列出網路 socket。
列出終端機上的所有 TCP、UDP 和 SCTP socket,包括 Erlang 執行時期系統以及應用程式建立的 socket。
可以使用下列選項:
port
- 連接埠的內部索引。module
- socket 的回呼模組。recv
- socket 收到的位元組數量。sent
- 從 socket 送出的位元組數量。owner
- socket 擁有者進程。local_address
- socket 的本機位址。foreign_address
- 連線另一端的位址和連接埠。state
- 連線狀態。type
- STREAM 或 DGRAM 或 SEQPACKET。
Options
引數也可能為 (自 OTP 27.0 起)
show_ports
- 不將連接埠號碼(「local_address」和「foreign_address」)轉換為服務名稱。
取得關於 socket 的資訊。
傳回一個包含關於 socket 各種資訊的 term。
-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 監控。
如果要監控的 Socket
不存在,或者當觸發監控時,會傳送一個具有以下模式的 'DOWN'
訊息
{'DOWN', MonitorRef, Type, Object, Info}
MonitorRef
- 此函數的傳回值。Type
- socket 的類型,可以是下列atom/0
之一:port
或socket
。Object
- 被監控的實體,即觸發事件的 socket。Info
- socket 的終止原因或nosock
(呼叫此函數時Socket
不存在)。
多次呼叫同一個 Socket
的 inet:monitor/1
並非錯誤;每次呼叫都會建立一個監控器。
當 socket 以任何方式關閉時,例如 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()}.
傳回 socket 遠端的位址。
傳回連線另一端的位址和 port。
請注意,對於 SCTP socket,此函數只傳回 socket 的其中一個對等位址。函數 peernames/1,2
會傳回所有位址。
-spec peernames(Socket :: socket()) -> {ok, [{ip_address(), port_number()} | returned_non_ip_address()]} | {error, posix()}.
等同於 peernames(Socket, 0)
。
請注意,此函數對於 SCTP 一對多樣式的 socket 的行為,並未由 SCTP Sockets API Extensions 定義。
-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().
傳回 socket 所有遠端的位址。
傳回 socket 的關聯 Assoc
的遠端端所有位址/port 號碼對的清單。
此函數可以傳回多重宿主 socket 的多個位址,例如 SCTP socket。對於其他 socket,它會傳回一個元素的清單。
請注意,參數 Assoc
由 SCTP Sockets API Extensions 定義為在一對一樣式的 socket 中被忽略。不幸的是,特殊值 0
的含義未定義,因此對於一對多樣式的 socket 的行為也是未定義的。
-spec port(Socket) -> {ok, Port} | {error, any()} when Socket :: socket(), Port :: port_number().
傳回 socket 的本機埠號。
-spec setopts(Socket, Options) -> ok | {error, posix()} when Socket :: socket(), Options :: [socket_setopt()].
設定 socket 的一個或多個選項。
在 Socket
上設定 Options
的清單。
可以使用下列選項:
{active, true | false | once | N}
- 如果值為true
,這是預設值,則從 socket 收到的所有內容都會以訊息形式傳送到接收程序。如果值為
false
(被動模式),則程序必須透過呼叫gen_tcp:recv/2,3
、gen_udp:recv/2,3
或gen_sctp:recv/1,2
(取決於 socket 的類型)來明確接收傳入的資料。如果值為
once
({active, once}
),則從 socket 發出一則資料訊息給程序。若要接收另一則訊息,必須再次呼叫setopts/2
,並使用選項{active, once}
。如果值是介於 -32768 到 32767(含)之間的整數
N
,則該值會新增至 socket 已傳送到控制程序的資料訊息計數。socket 的預設訊息計數為0
。如果指定負值,且其絕對值大於或等於 socket 目前的訊息計數,則 socket 的訊息計數會設定為0
。一旦 socket 的訊息計數達到0
,無論是因為將接收到的資料訊息傳送到程序,還是被明確設定,程序都會收到一個特殊的訊息,該訊息特定於 socket 的類型,表示 socket 已進入被動模式。一旦 socket 進入被動模式,若要接收更多訊息,必須再次呼叫setopts/2
以將 socket 設定回主動模式。當使用
{active, once}
或{active, N}
時,socket 在收到資料時會自動變更行為。當與連線導向的 socket(即gen_tcp
)結合使用時,這可能會令人困惑,因為行為為{active, false}
的 socket 報告關閉的方式與行為為{active, true}
的 socket 不同。為了簡化程式設計,當對等方關閉,且在{active, false}
模式下偵測到時,設定為{active, once}
、{active, true}
或{active, N}
模式的 socket 仍然會產生訊息{tcp_closed, Socket}
。因此,可以安全地假設當 socket 在{active, true}
和{active, false}
模式之間來回變更時,最終會出現訊息{tcp_closed, Socket}
,後面可能會接著 socket port 終止(取決於選項exit_on_close
)。然而,偵測到對等方關閉的時間完全取決於底層的 TCP/IP 堆疊和協定。請注意,
{active, true}
模式不提供流量控制;快速的傳送者可以輕鬆地以傳入的訊息淹沒接收者。{active, N}
模式也是如此,當訊息計數大於零時。僅當您的上層協定提供自己的流量控制(例如,確認收到的訊息),或交換的資料量很小時,才使用主動模式。使用
{active, false}
模式、{active, once}
模式,或使用N
值適合應用程式的{active, N}
模式來提供流量控制。另一端傳送的速度不能快於接收端讀取的速度。{buffer, Size}
- 驅動程式使用的使用者層級緩衝區的大小。請勿與對應於核心 socket 緩衝區的sndbuf
和recbuf
選項混淆。對於 TCP,建議val(buffer) >= val(recbuf)
,以避免因不必要的複製而導致效能問題。對於 UDP,也適用相同的建議,但最大值不應大於網路路徑的 MTU。val(buffer)
會在設定recbuf
時自動設定為上述最大值。但是,由於為recbuf
設定的大小通常會變大,因此建議您使用getopts/2
來分析作業系統的行為。請注意,這也是單次 recv 呼叫可以接收的最大資料量。如果您使用高於正常 MTU 的值,請考慮將緩衝區設定得更高。
{delay_send, Boolean}
- 通常,當 Erlang 程序傳送至 socket 時,驅動程式會嘗試立即傳送資料。如果失敗,驅動程式會使用任何可用的方法將訊息排入佇列,以便在作業系統表示可以處理時傳送。設定{delay_send, true}
會使所有訊息都排入佇列。然後,傳送到網路的訊息會更大,但數量更少。此選項影響傳送請求與 Erlang 程序的排程,而不是變更 socket 的任何實際屬性。此選項是特定於實作的。預設值為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
的唯一原因是,如果您想要在偵測到關閉後繼續傳送資料到 socket,例如,當對等端使用gen_tcp:shutdown/2
來關閉寫入端時。{exclusiveaddruse, Boolean}
- 在 Windows 上啟用/停用獨佔位址/埠使用。也就是說,透過啟用此選項,您可以防止其他 socket 繫結到相同的位址/埠。預設情況下,此選項會停用。也就是說,其他 socket 可以透過設定{reuseaddr, true}
與{reuseport, true}
的組合來使用相同的位址/埠,除非在Socket
上設定了{exclusiveaddruse, true}
。在非 Windows 系統上,此選項會被靜默忽略。注意
對於使用
inet_backend = socket
建立的 socket,目前不支援此選項{header, Size}
- 只有在建立 socket 時指定了binary
選項,此選項才有意義。如果指定了header
選項,則從 socket 收到的資料的前Size
個位元組是列表的元素,其餘資料是指定為同一列表尾部的二進制資料。例如,如果Size == 2
,則收到的資料會符合[Byte1, Byte2 | Binary]
。{high_msgq_watermark, Size}
- 當訊息佇列上的資料量達到此限制時,socket 訊息佇列會設定為忙碌狀態。請注意,此限制僅適用於尚未到達 ERTS 內部 socket 實作的資料。預設值為 8 kB。如果 socket 訊息佇列忙碌或 socket 本身忙碌,則傳送資料到 socket 的傳送器會被暫停。
如需詳細資訊,請參閱選項
low_msgq_watermark
、high_watermark
和low_watermark
。請注意,分發 socket 會停用
high_msgq_watermark
和low_msgq_watermark
的使用。改為使用 分發緩衝區忙碌限制,這是一個類似的功能。{high_watermark, Size}
(TCP/IP sockets) - 當 ERTS socket 實作內部排隊的資料量達到此限制時,socket 會設定為忙碌狀態。預設值為 8 kB。如果 socket 訊息佇列忙碌或 socket 本身忙碌,則傳送資料到 socket 的傳送器會被暫停。
如需詳細資訊,請參閱選項
low_watermark
、high_msgq_watermark
和low_msqg_watermark
。{ipv6_v6only, Boolean}
- 將 socket 限制為僅使用 IPv6,禁止任何 IPv4 連線。這僅適用於 IPv6 socket(選項inet6
)。在大多數平台上,此選項必須在將 socket 與位址關聯之前設定。因此,僅在建立 socket 時指定它才是合理的,而當呼叫包含此描述的函式 (
setopts/2
) 時,則不應使用它。將此選項設定為
true
的 socket 行為是唯一可移植的行為。當 IPv6 是新事物時,使用 IPv6 處理所有流量的最初想法現在不被 FreeBSD 推薦(您可以使用{ipv6_v6only,false}
來覆寫建議的系統預設值),OpenBSD 禁止(支援的 GENERIC 核心),並且在 Windows 上不可能(Windows 有單獨的 IPv4 和 IPv6 協定堆疊)。大多數 Linux 發行版仍然具有false
的系統預設值。作業系統之間將 IPv6 與 IPv4 流量分離的此策略轉變已經發展,因為它逐漸證明很難且複雜地獲得雙堆疊實作的正確和安全。在某些平台上,此選項唯一允許的值是
true
,例如,OpenBSD 和 Windows。在此情況下,嘗試在建立 socket 時將此選項設定為false
會失敗。在不存在此選項的平台上設定此選項會被忽略。使用
getopts/2
取得此選項會傳回無值,也就是說,傳回的列表不包含{ipv6_v6only,_}
元組。在 Windows 上,此選項不存在,但它會模擬為具有值true
的唯讀選項。因此,在建立 socket 時將此選項設定為
true
永遠不會失敗,除非可能在您自訂核心以僅允許false
的平台上,例如,在 OpenBSD 上可以執行(但很麻煩)。如果您使用
getopts/2
讀回選項值且未取得值,則表示主機作業系統中不存在該選項。在這種情況下,在相同埠上接聽的 IPv6 和 IPv4 socket,以及 IPv6 socket 取得 IPv4 流量的行為不再是可預測的。{keepalive, Boolean}
(TCP/IP sockets) - 啟用/停用在沒有其他資料交換時在已連線的 socket 上進行定期傳輸。如果另一端沒有回應,則會將連線視為中斷,並將錯誤訊息傳送至控制程序。預設值為false
。{linger, {true|false, Seconds}}
- 決定在close/1
socket 呼叫中清除未傳送資料的逾時時間(以秒為單位)。第一個元件表示是否啟用 linger,第二個元件是以秒為單位的清除逾時時間。有 3 種替代方案
{false, _}
- close/1 或 shutdown/2 立即傳回,而不等待資料清除,並在背景中關閉。{true, 0}
- 在關閉時中止連線。捨棄仍在傳送緩衝區中的任何資料,並向對等端傳送 RST。這可避免 TCP 的 TIME_WAIT 狀態,但會留下建立此連線的另一個「化身」的可能性。
{true, Time} when Time > 0
- close/1 或 shutdown/2 將不會傳回,直到 socket 的所有排隊訊息都已成功傳送,或達到 linger 超時 (Time) 為止。
{low_msgq_watermark, Size}
- 如果 socket 訊息佇列處於忙碌狀態,則當訊息佇列中排隊的資料量低於此限制時,socket 訊息佇列會設定為非忙碌狀態。請注意,此限制僅適用於尚未到達 ERTS 內部 socket 實作的資料。預設值為 4 kB。由於訊息佇列忙碌或 socket 忙碌而被暫停的傳送器會在 socket 訊息佇列和 socket 不忙碌時恢復。
如需詳細資訊,請參閱選項
high_msgq_watermark
、high_watermark
和low_watermark
。請注意,分發 socket 會停用
high_msgq_watermark
和low_msgq_watermark
的使用。它們改為使用 分發緩衝區忙碌限制,這是一個類似的功能。{low_watermark, Size}
(TCP/IP sockets) - 如果 socket 處於忙碌狀態,則當 ERTS socket 實作內部排隊的資料量低於此限制時,socket 會設定為非忙碌狀態。預設值為 4 kB。由於訊息佇列忙碌或 socket 忙碌而被暫停的傳送器會在 socket 訊息佇列和 socket 不忙碌時恢復。
如需詳細資訊,請參閱選項
high_watermark
、high_msgq_watermark
和low_msgq_watermark
。{mode, Mode :: binary | list}
- 收到的Packet
會依照Mode
的定義傳遞。{netns, Namespace :: file:filename_all()}
- 設定 socket 的網路命名空間。參數Namespace
是定義命名空間的檔案名稱,例如,"/var/run/netns/example"
,通常由命令ip netns add example
建立。此選項必須在建立 socket 的函式呼叫中使用,也就是gen_tcp:connect/3,4
、gen_tcp:listen/2
、gen_udp:open/1,2
或gen_sctp:open/0,1,2
,以及getifaddrs/1
。此選項使用 Linux 特有的 syscall
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 socket 似乎不支援網路命名空間。Namespace
是一個檔案名稱,其編碼和解碼方式如模組file
中所述,但有以下例外情況:- 模擬器標誌
+fnu
會被忽略。 - 如果儲存的檔案名稱無法解碼,此選項的
getopts/2
會傳回該檔案名稱的二進位資料。只有在您使用無法使用模擬器的檔案名稱編碼解碼的二進位資料設定選項時,才會發生這種情況:file:native_name_encoding/0
。
- 模擬器標誌
{bind_to_device, Ifname :: binary()}
- 將 socket 綁定到特定的網路介面。此選項必須在建立 socket 的函式呼叫中使用,也就是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 特定的 socket 選項
SO_BINDTODEVICE
,例如在 Linux 核心 2.0.30 或更新版本中,因此只有在為此類作業系統編譯執行時系統時才存在。在 Linux 3.8 之前,可以設定此 socket 選項,但無法使用
getopts/2
擷取。自 Linux 3.8 起,此選項是可讀取的。虛擬機器也需要提升的權限,無論是以超級使用者身分執行,還是(對於 Linux)擁有
CAP_NET_RAW
功能。此選項的主要用例是將 socket 綁定到 Linux VRF 實例中。
list
- 收到的Packet
會以清單形式傳遞。binary
- 收到的Packet
會以二進位資料形式傳遞。{nodelay, Boolean}
(TCP/IP socket) - 如果Boolean == true
,則會為 socket 開啟TCP_NODELAY
選項,這表示也會立即傳送少量資料。此選項不支援
domain = local
,但如果inet_backend =/= socket
,則此錯誤會被忽略。{nopush, Boolean}
(TCP/IP socket) - 這在 BSD 上會轉換為TCP_NOPUSH
,在 Linux 上會轉換為TCP_CORK
。如果
Boolean == true
,則會為 socket 開啟對應的選項,這表示會累積少量資料,直到有足夠的 MSS 大小資料可用,或此選項關閉為止。請注意,雖然
TCP_NOPUSH
socket 選項在 OSX 上可用,但其語義非常不同(例如,取消設定它不會導致立即傳送累積的資料)。因此,nopush
選項在 OSX 上會被故意忽略。{packet, PacketType}
(TCP/IP socket) - 定義要用於 socket 的封包類型。可能的值: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
格式傳回。被動模式下的 socket 會從gen_tcp:recv
傳回{ok, HttpPacket}
,而作用中 socket 會傳送類似{http, Socket, HttpPacket}
的訊息。httph | httph_bin
- 這兩種類型通常不是必需的,因為 socket 在讀取第一行後,會內部自動從http
/http_bin
切換到httph
/httph_bin
。然而,有時它們可能會很有用,例如從分塊編碼中解析尾部。
{packet_size, Integer}
(TCP/IP socket) - 設定允許的最大封包主體長度。如果封包標頭指示封包長度大於允許的最大長度,則該封包會被視為無效。如果封包標頭對於 socket 接收緩衝區而言太大,也會發生相同情況。對於面向行的協定(
line
、http*
),packet_size
選項也會確保接受長度不超過指定長度的行,並且不會因為內部緩衝區限制而被視為無效。{line_delimiter, Char}
(TCP/IP socket) - 為面向行的協定 (line
) 設定行分隔字元。預設為$\n
。{raw, Protocol, OptionNum, ValueBin}
- 請參閱下方。{read_ahead, Boolean}
- 如果設定為false
,則會避免從作業系統 socket 層預讀。此選項的預設值為true
,這會加快封包標頭的剖析速度。設定false
會產生效能損失,因為必須先讀取封包標頭,才能確切知道要為內文讀取多少位元組,這大致會使讀取作業的次數增加一倍。例如,在切換到 kTLS 之前,此選項的使用至關重要,它會透過設定特殊的(原始)socket 選項來啟動作業系統 socket 層加密和解密。因此,如果 Erlang socket 層已經預讀,它會讀取本來要讓作業系統 socket 層解密的位元組,這會導致連線的封包解密失效。
警告
對於在封包標頭中沒有固定位置封包長度的封包模式,例如
line
或asn1
,不預讀可能會變得非常低效,因為有時唯一的方法是一次讀取一個位元組,直到找到長度或封包結尾為止。{read_packets, Integer}
(UDP socket) - 設定在有資料可用時,不經過 socket 介入,最多讀取的 UDP 封包數。當已讀取並傳送到目標程序的封包數量達到這個數字時,在收到有可用資料的新通知之前,不會讀取新的封包。預設值為5
。如果將此參數設定得太高,系統可能會因為 UDP 封包洪水而沒有反應。{recbuf, Size}
- 要用於 socket 的最小接收緩衝區大小。建議您使用getopts/2
來擷取作業系統設定的大小。{recvtclass, Boolean}
- 如果設定為true
,則會在實作 socket 的協定IPPROTO_IPV6
選項IPV6_RECVTCLASS
或IPV6_2292RECVTCLASS
的平台上,啟用傳回收到的TCLASS
值。無論平台傳回IPV6_TCLASS
還是IPV6_RECVTCLASS
CMSG 值,該值都會以{tclass,TCLASS}
元組傳回。對於支援使用酬載資料接收輔助資料的面向封包 socket(
gen_udp
和gen_sctp
),TCLASS
值會包含在 輔助資料清單中,以延伸傳回元組的方式傳回。對於面向串流的 socket(gen_tcp
),取得TCLASS
值的唯一方法是平台是否支援pktoptions
選項。{recvtos, Boolean}
- 如果設定為true
,則會在實作 socket 的協定IPPROTO_IP
選項IP_RECVTOS
的平台上,啟用傳回收到的TOS
值。無論平台傳回IP_TOS
還是IP_RECVTOS
CMSG 值,該值都會以{tos,TOS}
元組傳回。對於支援使用酬載資料接收輔助資料的面向封包 socket(
gen_udp
和gen_sctp
),TOS
值會包含在 輔助資料清單中,以延伸傳回元組的方式傳回。對於面向串流的 socket(gen_tcp
),取得TOS
值的唯一方法是平台是否支援pktoptions
選項。{recvttl, Boolean}
- 如果設定為true
,則會在實作 socket 的協定IPPROTO_IP
選項IP_RECVTTL
的平台上,啟用傳回收到的TTL
值。無論平台傳回IP_TTL
還是IP_RECVTTL
CMSG 值,該值都會以{ttl,TTL}
元組傳回。對於支援使用酬載資料接收輔助資料的面向封包 socket(
gen_udp
和gen_sctp
),TTL
值會包含在 輔助資料清單中,以延伸傳回元組的方式傳回。對於面向串流的 socket(gen_tcp
),取得TTL
值的唯一方法是平台是否支援pktoptions
選項。{reuseaddr, Boolean}
- 允許或不允許重複使用本機位址。預設情況下,不允許重複使用。注意
在 Windows 上,除非同時設定
{reuseport, true}
,否則{reuseaddr, true}
將不會有任何效果。如果兩者都設定,則會啟用 Windows Socket 選項SO_REUSEADDR
。這是因為在 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
Socket 選項。 - 在 OTP 25.2 到 OTP 26.0 的前身版本之間,如果設定了
{reuseaddr, true}
,則底層的SO_REUSEADDR
Socket 選項僅在 UDP Socket 上設定,在其他 Socket 上則會靜默忽略。
另請參閱
exclusiveaddruse
選項。- 在 OTP 25.0 之前,
{reuseport, Boolean}
- 允許或不允許重複使用本機端口,這可能會或可能不會根據底層作業系統進行負載平衡。預設情況下,不允許重複使用。另請參閱reuseport_lb
。注意
在 Windows 上,除非同時設定
{reuseaddr, true}
,否則{reuseport, true}
將不會有任何效果。如果兩者都設定,則會啟用 Windows Socket 選項SO_REUSEADDR
。這是因為在 Windows 上設定SO_REUSEADDR
在某種程度上具有與在 BSD 上同時設定SO_REUSEADDR
和SO_REUSEPORT
相同的行為。reuseport
選項自 OTP 26.0 起引入。另請參閱
exclusiveaddruse
選項。注意
reuseport
可能與或可能不與reuseport_lb
底層選項相同,這取決於底層作業系統。例如,在 Linux 上它們是相同的。當它們是相同的底層選項時,同時操作它們可能會導致它們以令人意外的方式互動。例如,啟用reuseport
然後停用reuseport_lb
,最終兩者都會被停用。注意
對於使用
inet_backend = socket
建立的 socket,目前不支援此選項{reuseport_lb, Boolean}
- 允許或不允許重複使用本機端口並進行負載平衡。預設情況下,不允許重複使用。另請參閱reuseport
。注意
reuseport_lb
可能與或可能不與reuseport
底層選項相同,這取決於底層作業系統。例如,在 Linux 上它們是相同的。當它們是相同的底層選項時,同時操作它們可能會導致它們以令人意外的方式互動。例如,啟用reuseport_lb
然後停用reuseport
,最終兩者都會被停用。注意
對於使用
inet_backend = socket
建立的 socket,目前不支援此選項{send_timeout, Integer}
- 僅允許用於連線導向的 Socket。指定等待底層 TCP 堆疊接受傳送操作的最長時間。當超過限制時,傳送操作會傳回
{error, timeout}
。已傳送封包的數量是未知的;因此,只要發生逾時,就應關閉 Socket(請參閱下方的send_timeout_close
)。預設值為infinity
。{send_timeout_close, Boolean}
- 僅允許用於連線導向的 Socket。與
send_timeout
一起使用,以指定當傳送操作傳回{error, timeout}
時是否自動關閉 Socket。建議的設定是true
,這會自動關閉 Socket。由於回溯相容性,預設值為false
。{show_econnreset, Boolean}
(TCP/IP Socket) - 當此選項設定為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}
訊息,如同任何其他 Socket 錯誤的情況一樣。當偵測到 TCP 對等端已傳送 RST 時,呼叫gen_tcp:send/2
也會傳回{error, econnreset}
。從
gen_tcp:accept/1
傳回的已連線 Socket 會從接聽 Socket 繼承show_econnreset
設定。{sndbuf, Size}
- 要用於 Socket 的傳送緩衝區最小大小。建議您使用getopts/2
來檢索作業系統設定的大小。{priority, Integer}
- 在實作此選項的平台上設定SO_PRIORITY
Socket 層級選項。不同系統之間的行為和允許範圍會有所不同。在未實作此選項的平台上會忽略此選項。請謹慎使用。{tos, Integer}
- 在實作此選項的平台上設定IP_TOS IP
層級選項。不同系統之間的行為和允許範圍會有所不同。在未實作此選項的平台上會忽略此選項。請謹慎使用。{tclass, Integer}
- 在實作此選項的平台上設定IPV6_TCLASS IP
層級選項。不同系統之間的行為和允許範圍會有所不同。在未實作此選項的平台上會忽略此選項。請謹慎使用。
除了這些選項之外,還可以使用原始選項規格。原始選項指定為一個四元組,以標籤 raw
開頭,後接通訊協定層級、選項編號和指定為二進位的選項值。這對應於 C Socket API 中 setsockopt
呼叫的第二、三和四個參數。選項值必須以平台的原生位元組順序編碼,如果需要結構,則必須遵循特定平台上的結構對齊慣例。
使用原始 Socket 選項需要對當前作業系統和 TCP 堆疊有詳細的了解。
範例
此範例與原始選項的使用有關。假設有一個 Linux 系統,您想在堆疊中的通訊協定層級 IPPROTO_TCP
上設定選項 TCP_LINGER2
。您知道在這個特定的系統上,它預設為 60(秒),但您想將特定 Socket 的值降低到 30。 inet
沒有明確支援選項 TCP_LINGER2
,但您知道通訊協定層級轉換為數字 6,選項編號轉換為數字 8,並且該值指定為 32 位元整數。您可以使用此程式碼行來設定名為 Sock
的 Socket 選項
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 Socket 的預設選項可以使用本手冊頁開頭提及的核心組態參數來變更。
-spec sockname(Socket :: socket()) -> {ok, {ip_address(), port_number()} | returned_non_ip_address()} | {error, posix()}.
傳回 socket 的本機位址和埠號。
請注意,對於 SCTP Socket,此函數僅傳回其中一個 Socket 位址。函數 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().
傳回 socket 的所有本機位址。
傳回指定關聯 Assoc
的 Socket 所有本機位址/埠號碼配對的清單。
此函數可以傳回多重宿主 socket 的多個位址,例如 SCTP socket。對於其他 socket,它會傳回一個元素的清單。
請注意,根據 SCTP Socket API Extensions 的定義,參數 Assoc
對於一對一的樣式 Socket 會被忽略。對於一對多的樣式 Socket,定義特殊值 0
表示傳回的位址必須不帶任何特定的關聯。不同的 SCTP 實作對此的解釋會有些不同。