我对当前的方法不满意,只是尝试重新设计在 Erlang 中构建协议栈的方式。该功能按重要性排序:
表现
添加新协议变体的灵活性和实施速度
它将有助于开发从 shell 探索协议变体
我当前的型号(这个问题已经描述过除了通过函数调用发送()和通过消息接收的丑陋的不对称性之外,)已经达到了它的极限。
整个协议引擎的整体图是这样的:
底部部分:
顶部部分:
由事件发生触发(一般意义上不是 event_handler 意义上的)是面向连接的协议端(例如,connect()
and close()
语义。
协议栈的顶端可能只能动态启动,因为堆叠在一起形成堆栈的模块是动态可配置的,并且可能会因连接而异。
目前计划将传递一个模块名称列表+来自顶层的可选参数,这些参数在connect()
在堆栈中调用。
顶级进程将被链接,因此当这里出现任何问题时,整个连接都会失败。
模块类型及其之间的通信类型
目前发现的模块有以下几种:
层间通信类型:
独立发送和接收数据包(从外部看是独立的)
发送某些内容的同步调用会阻塞,直到有答案为止,然后将结果作为返回值返回。
与多个模块对话的多路复用器(这是我的定义,以方便讨论)
具有不同连接点(当前由原子命名)的解复用器可以与朝上的模块通信。
目前,我唯一的解复用器位于堆栈的静态底部,而不是动态创建的顶部。多路复用器目前仅位于顶部。
在我之前链接的问题处理的答案和评论中,我听说 API 通常应该只包含函数而不是消息,除非另有说服力,否则我同意这一点。
请原谅对问题的冗长解释,但我认为它对于各种协议实现仍然具有普遍用途。
我将在答案中写下到目前为止我计划的内容,并且还将解释最终的实现以及我稍后的经验,以便在这里实现一些普遍有用的东西。
我将添加到目前为止我计划的内容作为答案的一部分:
-
connect 传递了一个要堆栈的模块列表,在参数的情况下看起来像一个 proplist,例如:
connect([module1, module2, {module3, [params3]}], param0, further_params)
每一层都剥离头部并调用下一层连接。
-
connect()
“以某种方式”向上和/或向下层传递有趣的参考
- send for async 向下发送堆栈将由较低级别的连接返回
- 用于异步接收堆栈的recv将作为参数传递给较低级别的连接
- 调用同步发送并等待返回的回复 - 不确定如何处理这些,可能也从较低级别的连接返回
-
多路复用器路由列表可能如下所示
connect([module1, multiplexer, [[m_a_1, m_a_2, {m_a_3, [param_a_3]}],
[m_b_1, m_b_2],
[{m_c_1, [param_c_1]}, m_c_2]], param0,
further_params]).
目前我决定不会有额外的同步调用函数,我只是使用 send 来实现。
在这种情况下,有一个无状态模块的想法的实现示例:encode/1
and decode/1
对数据包进行一些 for 和 back 转换,例如将二进制表示解析为记录并返回:
connect(Chan, [Down|Rest], [], Recv_fun) ->
{Down_module, Param} = case Down of
{F, P} -> {F, P};
F when is_atom (F) -> {F, []}
end,
Send_fun = Down_module:connect(Chan, Rest, Param,
fun(Packet) -> recv(Packet, Recv_fun) end),
{ok, fun(Packet) -> send(Packet, Send_fun) end}.
send(Packet, Send_fun) ->
Send_fun(encode(Packet)).
recv(Packet, Recv_fun) ->
Recv_fun(decode(Packet)).
一旦我有一个有状态的例子,我也会发布它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)