gen_tcp:accept错误侦听套接字已关闭?

时间:2016-12-12 16:52:27

标签: sockets tcp erlang

为初学者编写一个非常简单的TCP服务器,但对于我的生活,gen_tcp:在我的接受中接受' 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_tcp:listen之后和在accept_loop中运行erlang:port_info(ListenSocket)。两者都输出相同的数据,如果我将gen_tcp:accept放在主线程中或者gen_tcp:listen之后它按预期工作。我在生成新流程时做错了什么?

P.S我使用本教程作为参考:http://20bits.com/article/erlang-a-generalized-tcp-server

0 个答案:

没有答案