将控制权从一个 gen_fsm 传递给另一个

Pass control from one gen_fsm to another

我正在创建一个通用的 Erlang 服务器,它应该能够同时处理数百个客户端连接。为简单起见,我们假设服务器为每个客户端执行一些基本计算,例如,对客户端提供的每两个值进行加法或减法。

作为起点,我使用 this tutorial 进行基本的 TCP 客户端-服务器交互。代表监督树的摘录:

                +----------------+
                | tcp_server_app |
                +--------+-------+
                         | (one_for_one)
        +----------------+---------+
        |                          |
+-------+------+           +-------+--------+
| tcp_listener |           + tcp_client_sup |
+--------------+           +-------+--------+
                                   | (simple_one_for_one)
                             +-----|---------+
                           +-------|--------+|
                          +--------+-------+|+
                          |  tcp_echo_fsm  |+
                          +----------------+

我想扩展此代码并允许 tcp_echo_fsm 将对套接字的控制权传递给两个模块之一:tcp_echo_addition(计算每两个客户端值的加法),或 tcp_echo_subtraction(计算每两个客户端值之间的减法)。

tcp_echo_fsm 将根据来自客户端的第一条消息选择哪个模块来处理套接字,例如,如果客户端发送 <<start_addition>>,那么它会将控制权传递给 tcp_echo_addition.

之前的图变成:

                +----------------+
                | tcp_server_app |
                +--------+-------+
                         | (one_for_one)
        +----------------+---------+
        |                          |
+-------+------+           +-------+--------+
| tcp_listener |           + tcp_client_sup |
+--------------+           +-------+--------+
                                   | (simple_one_for_one)
                             +-----|---------+
                           +-------|--------+|
                          +--------+-------+|+
                          |  tcp_echo_fsm  |+
                          +----------------+
                                  |
                                  |
                 +----------------+---------+
         +-------+-----------+      +-------+--------------+
         | tcp_echo_addition |      + tcp_echo_subtraction |
         +-------------------+      +-------+--------------+

我的问题是:

  1. 我走的路对吗?我正在使用的教程是可扩展 TCP 服务器设计的良好起点吗?

  2. 如何将控制权从一个 gen_fsm(即 tcp_echo_fsm)传递给另一个 gen_fsm(tcp_echo_additiontcp_echo_subtraction)?或者更好:这是设计服务器的 correct/clean 方式吗? related question 表明在 gen_fsm 和另一个模块之间传递控制并非易事,这种方法可能有问题。

对于 2,您可以使用 gen_tcp:controlling_process/2 来传递对 tcp 连接的控制:http://erlang.org/doc/man/gen_tcp.html#controlling_process-2

对于 1,与将减法和加法逻辑作为有限状态机中已定义状态的一部分进行处理相比,我不确定产生新模块的价值。这样做会创建现在 运行 在您的监督树之外的代码,因此更难处理错误和重新启动。为什么不将加法和减法定义为状态机中的不同状态处理这两种状态中的逻辑?

您可以创建 tcp_echo_fsm:subtraction_state/2,3tcp_echo_fsm:addition_state/2,3 来处理此逻辑并使用您的第一条消息转换到适当的状态,而不是增加应用程序的复杂性。