【发布时间】:2011-04-27 02:54:58
【问题描述】:
我注意到发送到 gen_fsm 进程的 pid 的消息在状态回调中作为事件匹配。这只是偶然还是我可以依赖此功能?
通常我希望发送到 gen_fsm 的一般消息会显示在 handle_info/3 回调中,并认为我必须使用 gen_fsm:send_event 重新发送它。
gen_fsm 是否首先尝试将消息与状态回调匹配,然后始终与 handle_info/3 回调匹配?还是仅当它不匹配状态回调子句时?
但是,当我尝试它时,我的消息似乎根据调试输出被处理了两次。
所以基本上这个问题也可以表述为:如何正确处理接收到的消息作为 gen_fsm 状态函数中的事件?
澄清:对于这个问题,应该考虑给出一些事件是通过传递消息而发生的。
我知道,在许多情况下,仅通过对 fsm 使用函数调用来使协议可见是一种更简洁的方法。
我不太确定这是否会改进提到的 gen_fsm 必须适应的当前框架:不同的协议栈,其中每一层调用一个 connect() 函数来附加(有时启动)较低层。数据包通过调用函数(发送)被发送到较低层,并由receive发送消息接收。很像 gen_tcp。
通过查看 gen_fsm 的代码,我已经发现一般消息仅传递给 handle_info,因此唯一的问题是直接从 handle_info/3 回调调用状态函数还是使用 gen_fsm:send_event 重新发送。
【问题讨论】:
-
我在这里理解正确吗,您是否仅将 gen_fsm 用于某些协议栈而不是全部?如果是这样,为什么?为什么不以相同的方式实现堆栈的所有 Erlang 部分?这将使您在发送和接收消息的方式上保持一致。
-
我一直在取消 {ok, Pid} = connect(), send(Pid, Data) 并接收 {resp, Data} 消息。所以我对栈中不同模块的API是一致的。我不一致的地方是当前对接收和发送的处理。
-
但是有相当多的预先存在的代码使用这种范例,所以它努力改变一切。不对堆栈的所有部分使用 gen_fsm 的原因是它实际上非常多样化的协议(汽车总线协议)通过 USB 多路复用。所以堆栈的部分在 gen_server、简单的 ad/hoc 服务器和无状态编码/解码过滤器和 gen_fsm 之间当然有所不同。
-
我接受了对整个协议栈进行更好设计的建议,并开始了一个新问题来讨论如何做到这一点的最佳方法:“如何设计灵活的 Erlang 协议栈创建API”参见“链接”部分
标签: erlang erlang-otp gen-fsm