1

你好我有这种情况:

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

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

来自文档:

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.
4

1 回答 1

4

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

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

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

解决方案是使用 socket 选项{active, once}

在此处查看 Erlang 套接字选项的描述

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

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

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

也可以在Learn You Some Erlang: More Control With Inet中找到对此的一个很好的描述

于 2012-08-18T10:32:26.600 回答