gen_tcp:accept が常に {error, closed} 応答を返す理由を特定するのに苦労しています。
基本的に、リッスン ソケットを作成するスーパーバイザがあります。
gen_tcp:listen(8081, [binary, {packet, 0}, {active, false}, {reuseaddr, true}]),
このソケットは、gen_server 動作の実装である子に渡されます。次に、子はソケットで接続を受け入れます。
accept(ListeningSocket, {ok, Socket}) ->
spawn(fun() -> loop(Socket) end),
accept(ListeningSocket);
accept(_ListeningSocket, {error, Error}) ->
io:format("Unable to listen on socket: ~p.~n", [Error]),
gen_server:call(self(), stop).
accept(ListeningSocket) ->
accept(ListeningSocket, gen_tcp:accept(ListeningSocket)).
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
io:format("~p~n", [Data]),
process_request(Data),
gen_tcp:send(Socket, Data),
loop(Socket);
{error, closed} -> ok
end.
スーパーバイザーと gen_server の BEAM バイナリをローカルにロードし、code:load_binary への RPC 呼び出しを介して別のノード (同じマシン上で実行) にロードします。次に、RPC 呼び出しを介してスーパーバイザーを実行します。これにより、サーバーが起動します。{error, closed} は、このシナリオでは常に gen_tcp:accept によって返されます。
ノード シェルにログインしているときにスーパーバイザとサーバを実行すると、サーバは問題なく接続を受け入れることができます。これには、接続を受け入れることができないリモート ノードへの「remsh」が含まれます。
シェルのみを使用して問題を再現できるようです。
[Terminal 1]: erl -sname node -setcookie abc -distributed -noshell
[Terminal 2]: erl -sname rpc -setcookie abc:
net_adm:ping('node@verne').
{ok, ListeningSocket} = rpc:call('node@verne', gen_tcp, listen, [8081, [binary, {packet, 0}, {active, true}, {reuseaddr, true}]]).
rpc:call('node@verne', gen_tcp, accept, [ListeningSocket]).
最終 RPC への応答は {error, closed} です。
これは、ソケット/ポートの所有権と関係がありますか?
参考までに、接続を待機しているクライアントはなく、タイムアウトはどこにも設定していません。