嗨,我有这种情况:
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.
答案 0 :(得分:4)
首先:拥有一个阻止您知道消息结束的协议并不是一个好主意。因此,如果您可以控制协议,那么最好有一个例子。您的协议消息前面的消息长度。
这就是说,通常最好不要阻止接收。
我想您希望在等待更多可能稍后到达的数据时阻止阻塞,以便在此期间处理来自其他进程的消息。
解决方法是使用套接字选项{active, once}
:
see description of Erlang socket opts here:
如果值为一次(
{active, once}
),则来自套接字的一条数据消息将被发送到进程。要再收到一条消息,必须使用setopts/2
选项再次调用{active, once}
。
您可能想尝试使用{active, true}
并获取每条数据的消息。这样做的问题在于您没有流量控制,因此如果您被数据淹没,VM会立即读取所有内容并将其填充到您的邮件邮箱中。这种情况很快就会失控,因为不断增长的邮箱会减慢您的速度,并且可能会占用您的所有记忆。
使用{active, once}
可以避免此消息泛滥。