Я изо всех сил пытаюсь определить причину, по которой gen_tcp:accept всегда возвращает ответ {ошибка, закрыто}.
По сути, у меня есть супервизор, который создает прослушивающий сокет:
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 локально и загружаю их на другой узел (который работает на той же машине) с помощью RPC-вызова code:load_binary. Затем я запускаю супервизор через вызов RPC, который, в свою очередь, запускает сервер. {error,closed} всегда возвращается gen_tcp:accept в этом сценарии.
Должен ли я запускать супервизор и сервер при входе в оболочку узла, тогда сервер может принимать соединения без проблем. Это включает в себя «remsh» для удаленного узла, который не смог бы принимать соединения, если бы я ранее выполнил RPC для неудачного запуска сервера.
Кажется, я могу воспроизвести проблему, используя только оболочку:
[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: {ошибка, закрыто}.
Может ли это быть как-то связано с владением сокетом/портом?
Если это поможет, нет клиентов, ожидающих подключения, и я нигде не устанавливаю тайм-ауты.