根据 Erlang 参考手册,发送运算符 (!)的语法是Expr1 ! Expr2.
它指出
Expr1可以是 形式的元组{Name, Node},其中 "Name是一个原子,Node是一个节点名称,也是一个原子”,并且- “分布式消息发送 [...] 永远不会失败”。
使用FreeSWITCH时mod_erlang_event(启动 Erlang C 节点)一起使用时,并使用任何原子作为 发送消息Name,它将导致响应:
$ erl -sname test -setcookie ClueCon
Erlang/OTP 19 [erts-8.2.1] [source] [64-bit] [async-threads:10] [kernel-poll:false]
Eshell V8.2.1 (abort with ^G)
(test@tr2)1> {polgarjenohivatalba, freeswitch@tr2} ! {api, msleep, 500}.
{api,msleep,500}
(test@tr2)2> receive X -> X after 1000 -> to end.
{ok,"+OK"}
(test@tr2)3> {vizbolveszikiazoxigent, freeswitch@tr2} ! holafafonok.
holafafonok
(test@tr2)4> flush().
Shell got {error,undef}
(test@tr2)5> nodes().
[]
(test@tr2)6> nodes(connected).
[freeswitch@tr2]
为什么这不适用于下面的两个常规 Erlang 节点?
上面的原子也不是注册的进程,消息发送感觉就像一个远程过程调用。
偷看了mod_erlang_event's source,但我没有太多 C 经验,也没有使用过非原生 Erlang 节点。感觉好像运行一个 C 节点会导致
(1) 运行一个 Erlang 节点
(2) 并自动启动一个进程
(使用 C 逻辑作为该receive进程的循环)
(3) 将匹配任何原子。
所以也许这就是为什么只有显式注册的进程才能与原生 Erlang 节点一起使用的原因。(再一次,我可能完全错了。)
起始节点“def”:
$ erl -sname def -setcookie lofa
Erlang/OTP 19 [erts-8.2.1] [source] [64-bit] [async-threads:10] [kernel-poll:false]
Eshell V8.2.1 (abort with ^G)
(def@tr2)1> {lofa, abc@tr2} ! miez.
miez
(def@tr2)2> nodes(connected).
[abc@tr2]
回到较早开始的节点“abc”:
$ erl -sname abc -setcookie lofa
Erlang/OTP 19 [erts-8.2.1] [source] [64-bit] [async-threads:10] [kernel-poll:false]
Eshell V8.2.1 (abort with ^G)
(abc@tr2)1> receive X -> X after 27000 -> timeout end.
timeout
(abc@tr2)2> nodes(connected).
[def@tr2]
和freeswitch@tr2也test@tr2立即连接为隐藏节点,但这种行为似乎与abc@tr2and相同def@tr2。