1

您可能知道,gen_tcp 有三种模式。{active, false},{active, true}{active, once}.

我已经阅读了一些关于{active, false}{active, true}的文档{active, once}。但是,我没有得到它。

{active, false}{active, true}和 和有什么不一样{active, once}

你能解释清楚吗?

4

2 回答 2

6

这是关于流量控制的:你有一个 Erlang 进程来处理传入的网络流量。通常你希望它对传入的数据包快速做出反应,但你不希望它的消息队列增长得​​比它处理它的速度更快——但在某些情况下你会有不同的目标。

使用{active, false},您可以明确控制进程何时接收传入流量:它仅在您调用 时发生gen_tcp:recv。但是,当进程在等待时gen_tcp:recv,它不能接收其他 Erlang 消息。也许其他一些 Erlang 进程正在发送一条消息,告诉它停止,但它还不知道,因为它正专注于获取网络输入。

使用{active, true},网络输入一旦可用就会作为消息发送到进程。这意味着您可以有一个receive表达式,它期望网络流量和来自其他进程的简单 Erlang 消息。如果您确信您的进程可以比输入更快地处理输入,这种操作模式可能很有用,但您最终可能会得到一个永远不会被清除的长消息队列。

{active, once}是两者之间的一种折衷方案:您以 Erlang 消息的形式接收传入数据,这意味着您可以将网络流量与其他工作混合,但在收到数据包后,您需要再次显式调用inet:setopts{active, once}接收更多数据,因此您可以决定多快您的进程接收消息。

从 Erlang/OTP 17.0 开始,还有另一个选项{active, N},其中 N 是一个整数。这意味着您可以在再次N致电之前收到消息inet:setopts。这可以提供更高的吞吐量,而不必放弃流量控制。

于 2018-07-17T08:43:23.153 回答
4

{active, false}
你必须通过调用 gen_tcp:recv() 从套接字读取数据块。

{active, true}
Erlang 自动为您从套接字读取数据块并将这些数据块收集成一个完整的消息并将消息放入进程邮箱中。您使用receive子句阅读消息。如果某些恶意行为者向您的邮箱充斥着消息,您的进程将会崩溃。

{active, once}
相当于{active, true}从套接字读取的第一个数据块,然后{active, false}是任何后续的数据块。

您还需要了解指定如何{packet, N}影响事物。见这里:Erlang gen_tcp not received anything

于 2018-07-16T17:07:24.373 回答