二郎神:避免竞争条件与调用gen_tcp:controlling_process(Erlang: A

2019-07-30 08:39发布

我采取按以下顺序简单TCP服务器:

{ok, LS} = gen_tcp:listen(Port,[{active, true}, {reuseaddr, true}, {mode, list}]),
{ok, Socket} =  gen_tcp:accept(LS),
Pid = spawn_link(M, F, [Socket]),           
gen_tcp:controlling_process(Socket, Pid) 

使用选项{活跃,真实}可能导致其中一个新的数据包到达插座过程中的“controlling_process”之前的竞争条件被调用,这将导致{TCP,插座,数据}消息抵达父亲proccess代替儿童。

这到底是怎么避免?

Answer 1:

You are right. In such cases you surely need {active, false} passed among listening socket options. Consider this snippet of code:

-define(TCP_OPTIONS, [binary, {active, false}, ...]).

...

start(Port) ->
    {ok, Socket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
    accept(Socket).

accept(ListenSocket) ->
    case gen_tcp:accept(ListenSocket) of
        {ok, Socket} ->
            Pid = spawn(fun() ->
                io:format("Connection accepted ~n", []),
                enter_loop(Socket)
            end),
            gen_tcp:controlling_process(Socket, Pid),
            Pid ! ack,
            accept(ListenSocket);
        Error ->
            exit(Error)
    end.

enter_loop(Sock) ->
    %% make sure to acknowledge owner rights transmission finished
    receive ack -> ok end,
    loop(Sock).

loop(Sock) ->
    %% set soscket options to receive messages directly into itself
    inet:setopts(Sock, [{active, once}]),
    receive
        {tcp, Socket, Data} ->
            io:format("Got packet: ~p~n", [Data]),
            ...,
            loop(Socket);
        {tcp_closed, Socket} ->
            io:format("Socket ~p closed~n", [Socket]);
        {tcp_error, Socket, Reason} ->
            io:format("Error on socket ~p reason: ~p~n", [Socket, Reason])
    end.

Thus you will not lost anything until controlling_process succeeds. It is known problem been discussed a lot over internets. If you wish to use ready to go solution you surely need to take a look at Ranch project.



Answer 2:

如果套接字处于活动状态, inet:tcp_controlling_process (由称为gen_tcp:controlling_process )设置套接字到被动,然后选择性地接收与该套接字的所有消息并将其发送到新的所有者,有效地将其移动到新所有者的消息队列。 然后,它的插座恢复活跃。

因此,有没有竞争条件:他们已经想到了这一点,在图书馆固定它。



文章来源: Erlang: Avoiding race condition with gen_tcp:controlling_process
标签: erlang