Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets gen_tcp:接受错误侦听套接字是否已关闭?_Sockets_Tcp_Erlang - Fatal编程技术网

Sockets gen_tcp:接受错误侦听套接字是否已关闭?

Sockets gen_tcp:接受错误侦听套接字是否已关闭?,sockets,tcp,erlang,Sockets,Tcp,Erlang,为初学者编写一个非常简单的TCP服务器,但对我来说,gen_TCP:accept在我的'accept_loop'函数中一直在调用时立即返回{error,closed}。到目前为止,我已经能够让其他一切工作到目前为止,但这一个真的难住了我。不知道我是否掉进了初学者的陷阱 无论如何,这是代码 -module(doom_server). -behaviour(gen_server). -export([start_link/1, handle_client/1, accept_loop/1, acc

为初学者编写一个非常简单的TCP服务器,但对我来说,gen_TCP:accept在我的'accept_loop'函数中一直在调用时立即返回
{error,closed}
。到目前为止,我已经能够让其他一切工作到目前为止,但这一个真的难住了我。不知道我是否掉进了初学者的陷阱

无论如何,这是代码

-module(doom_server).
-behaviour(gen_server).

-export([start_link/1, handle_client/1, accept_loop/1, accept/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

-define(TCP_OPTIONS, ).

-record(server_state, {
        port,
        ip=any,
        timeout=10,
        lsocket=null}).

start_link(_Args) ->
    gen_server:start_link(?MODULE, _Args, []).

init(_Args) ->
    % Get configuration from doom.config and create a new server state.
    Port = proplists:get_value(port, _Args),
    BindAddress = proplists:get_value(bind_address, _Args),
    Timeout = proplists:get_value(timeout, _Args),

    case gen_tcp:listen(Port, [binary,
        {packet, 0},
        {active, false},
        {reuseaddr, true}]) of
            {ok, ListenSocket} ->

                % Construct our server state.
                NewState = #server_state {
                    lsocket = ListenSocket,
                    port = Port,
                    ip=BindAddress,
                    timeout=Timeout
                },
                {ok, accept(NewState)};
            {error, Reason} ->
                io:format("Failed: ~w~n", [Reason]),
                {stop, Reason}
    end.

handle_cast({accepted, _Pid}, State=#server_state{}) ->
    {noreply, accept(State)}.

accept_loop({Server, ListenSocket, Timeout}) ->
    case gen_tcp:accept(ListenSocket, Timeout) of
        {ok, Socket} ->
             % Let the server spawn a new process and replace this loop
            gen_server:cast(Server, {accepted, self()}),
            handle_client(Socket);
        {error, Type} ->
            io:format("Error: ~w~n", [Type])
    end.

% To be more robust we should be using spawn_link and trapping exits
accept(State = #server_state{lsocket=ListenSocket, timeout=Timeout}) ->
    proc_lib:spawn(?MODULE, accept_loop, [{self(), ListenSocket, Timeout}]),
    State.

handle_client(Socket)->
    case gen_tcp:recv(Socket, 0) of
        {ok, Data} ->
            gen_tcp:send(Socket, Data),
            handle_client(Socket);
        {error, closed} ->
            ok
    end.

% We get compile warnings from gen_server unless we define these
handle_call(_Msg, _Caller, State) -> {noreply, State}.
handle_info(_Message, Library) -> {noreply, Library}.
terminate(_Reason, _Library) -> ok.
code_change(_OldVersion, Library, _Extra) -> {ok, Library}.
我在gen\u tcp:listen之后和accept\u循环中运行了
erlang:port\u info(ListenSocket)
。两者都输出相同的数据,如果我将
gen\u tcp:accept
放在主线程内或紧跟在
gen\u tcp:listen
之后,它将按预期工作。当我产生一个新流程时,我是否做错了什么


另外,我将本教程用作参考点:

您的accept参数可能提供了一个非常低的超时时间。事实并非如此。“{error,closed}if ListenSocket is closed”我一开始也以为是一样的。嗯……自从我使用Erlang以来,已经有很长一段时间了,但是你有没有尝试过
{active,true}
?我尝试过搞乱它,但没有运气。起初我认为这与accept需要在与gen_tcp相同的进程上运行有关:听着,但事实并非如此。我猜您是从一个进程启动
doom_服务器
,该进程在您希望服务器继续运行时死亡,但由于该进程链接到
doom_服务器
,因此,当它死机时,它会将服务器和侦听套接字一起关闭。在关闭的侦听套接字上调用
accept
将返回
{error,closed}
。您可能提供了非常低的超时作为accept参数。事实并非如此。“{error,closed}if ListenSocket is closed”我一开始也以为是一样的。嗯……自从我使用Erlang以来,已经有很长一段时间了,但是你有没有尝试过
{active,true}
?我尝试过搞乱它,但没有运气。起初我认为这与accept需要在与gen_tcp相同的进程上运行有关:听着,但事实并非如此。我猜您是从一个进程启动
doom_服务器
,该进程在您希望服务器继续运行时死亡,但由于该进程链接到
doom_服务器
,因此,当它死机时,它会将服务器和侦听套接字一起关闭。在关闭的侦听套接字上调用
accept
,将返回
{error,closed}