我想要做的是让一个 gen_server 进程接受一个新客户端并立即产生一个新的孩子来处理下一个。我看到的问题是,当套接字完成并随之终止时,它也会关闭侦听套接字,我不知道为什么,即使它不再引用它。
知道我做错了什么吗?
gen_server:
-module(simple_tcp).
-behaviour(gen_server).
%% API
-export([start_link/1, stop/0, start/0, start/1]).
%% gen-server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-define(DEFAULT_PORT, 1055).
-record(state, {port, lsock}).
start_link({port, Port}) ->
gen_server:start_link(?MODULE, [{port, Port}], []);
start_link({socket, Socket}) ->
gen_server:start_link(?MODULE, [{socket, Socket}], []).
start({port, Port}) ->
simple_tcp_sup:start_child({port, Port});
start({socket, Socket}) ->
simple_tcp_sup:start_child({socket, Socket}).
start() ->
start({port, ?DEFAULT_PORT}).
stop() ->
gen_server:cast(?SERVER, stop).
% Callback functions
init([{port, Port}]) ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true},{reuseaddr, true}]),
init([{socket, LSock}]);
init([{socket, Socket}]) ->
io:fwrite("Starting server with socket: ~p~n", [self()]),
{ok, Port} = inet:port(Socket),
{ok, #state{port=Port, lsock=Socket}, 0}.
handle_call(_Msg, _From, State) ->
{noreply, State}.
handle_cast(stop, State) ->
{stop, ok, State}.
handle_info({tcp, Socket, RawData}, State) ->
gen_tcp:send(Socket, io_lib:fwrite("Received raw data: ~p~n", [RawData])),
{noreply, State};
handle_info({tcp_error, _Socket, Reason}, State) ->
io:fwrite("Error: ~p~n", [Reason]),
{stop, normal, State};
handle_info(timeout, #state{lsock = LSock} = State) ->
case gen_tcp:accept(LSock) of
{ok, Sock} ->
io:fwrite("Accepting connection...~p~n", [self()]),
start({socket, LSock}),
{noreply, #state{lsock=Sock}};
{error, Reason} ->
io:fwrite("Error: ~p, ~p~n", [Reason, self()]),
{stop, normal, State}
end;
handle_info({tcp_closed, _Port}, State) ->
io:fwrite("Socket closed: ~p~n", [self()]),
simple_tcp_sup:kill_child(self()),
{stop, normal, State}.
terminate(_Reason, _State) ->
io:fwrite("Shutting down server: ~p~n", [self()]),
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
导师:
-module(simple_tcp_sup).
-behaviour(supervisor).
-export([start_link/0,
start_child/1
]).
-export([init/1]).
-define(SERVER, ?MODULE).
start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
start_child({socket, Socket}) ->
io:fwrite("Spawning child with socket...~n"),
supervisor:start_child(?SERVER, [{socket, Socket}]);
start_child({port, Port}) ->
io:fwrite("Spawning child with port...~n"),
supervisor:start_child(?SERVER, [{port, Port}]).
init([]) ->
Element = {simple_tcp, {simple_tcp, start_link, []},
temporary, brutal_kill, worker, [simple_tcp]},
Children = [Element],
RestartStrategy = {simple_one_for_one, 0, 1},
{ok, {RestartStrategy, Children}}.