在Erlang中通过RPC在远程节点上创建套接字时,无法接受套接字上的连接

时间:2015-07-03 05:57:42

标签: sockets erlang gen-tcp

我正在努力找出gen_tcp的原因:接受总是返回{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.

我在本地加载了supervisor和gen_server BEAM二进制文件,并通过对代码:load_binary的RPC调用将它们加载到另一个节点(在同一台机器上运行)上。 接下来,我通过RPC调用执行supervisor,然后启动服务器。{error,closed}总是由gen_tcp返回:在这种情况下接受。

我应该在登录节点shell时运行管理程序和服务器,然后服务器可以毫无问题地接受连接。这包括远程节点的'remsh',如果我之前没有成功启动服务器,那么它将无法接受连接。

我似乎能够通过单独使用shell来复制问题:

[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}。

这可能与套接字/端口所有权有关吗?

如果有帮助,没有客户等待连接,我也没有在任何地方设置超时。

1 个答案:

答案 0 :(得分:2)

每个rpc:call在目标节点上启动一个新进程来处理请求。在最后一个示例中,您的第一个调用在此过程中创建一个侦听套接字,并且当该进程在rpc调用结束时终止时,套接字将关闭。因此,由于已经关闭的侦听套接字,第二次尝试接受的rpc调用失败。

您的设计在某些方面似乎不同寻常。例如,让主管打开套接字是不正常的。您还说孩子是gen_server,但您显示了一个手动recv循环,如果在gen_server内运行会阻止它。您可以改为解释您要完成的任务,并请求帮助您设计出符合目标的设计。