erlang gen_tcp:recv block

时间:2012-08-17 23:52:58

标签: erlang recv gen-tcp

嗨,我有这种情况:

gen_tcp:connect(Address, Port, [{buffer, 1024},{active, false},{packet,0},{send_timeout, infinity}]).

我使用gen_tcp:recv(Sock,0),但是来自服务器的消息没有特定的结束模式,所以有什么方法可以阻止recv上的客户端阻塞?

来自doc:

do_recv(Sock, Bs) ->
    case gen_tcp:recv(Sock, 0) of
        {ok, B} ->
            do_recv(Sock, [Bs, B]);
        {error, closed} ->
            {ok, list_to_binary(Bs)}
    end.

1 个答案:

答案 0 :(得分:4)

首先:拥有一个阻止您知道消息结束的协议并不是一个好主意。因此,如果您可以控制协议,那么最好有一个例子。您的协议消息前面的消息长度。

这就是说,通常最好不要阻止接收。

我想您希望在等待更多可能稍后到达的数据时阻止阻塞,以便在此期间处理来自其他进程的消息。

解决方法是使用套接字选项{active, once}

see description of Erlang socket opts here

  

如果值为一次({active, once}),则来自套接字的一条数据消息将被发送到进程。要再收到一条消息,必须使用setopts/2选项再次调用{active, once}

您可能想尝试使用{active, true}并获取每条数据的消息。这样做的问题在于您没有流量控制,因此如果您被数据淹没,VM会立即读取所有内容并将其填充到您的邮件邮箱中。这种情况很快就会失控,因为不断增长的邮箱会减慢您的速度,并且可能会占用您的所有记忆。

使用{active, once}可以避免此消息泛滥。

也可以找到Learn You Some Erlang: More Control With Inet

的一个很好的描述