gpt4 book ai didi

erlang - gen_server 关闭监听套接字

转载 作者:行者123 更新时间:2023-12-04 23:29:26 30 4
gpt4 key购买 nike

我想要做的是让 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}}.

最佳答案

您的第三个 handle_info反转 Sock 的角色和 LSock .它应该通过 Sock子进程并保持其自己的状态不变。

BTW:重建是恶业State从头开始 ( #state{lsock=Sock} ) 你应该总是派生出新的 State从当前 State ( State#state{lsock=Sock} ),以防万一您以后添加更多状态变量。实际上,这现在有一个错误(尽管是良性错误),因为您正在丢弃端口号。

关于erlang - gen_server 关闭监听套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7291221/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com