绝对有竞争条件。我今天在 OTP 21.2 中遇到了它,这就是我在这里的原因。accept
数据包可以在返回时间和inet:tcp_controlling_process
将套接字设置为被动时间之间到达。
我只是想指出上面@Keynslug 答案的微小简化。套接字可以从非拥有进程设置为活动的,因此ack
消息传递和enter_loop
是不必要的
-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", []),
loop(Socket)
end),
gen_tcp:controlling_process(Socket, Pid),
inet:setopts(Socket, [{active, once}]),
accept(ListenSocket);
Error ->
exit(Error)
end.
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.