启动服务器使用:
erlc server.erl ; erl -eval 'server:start()'
在另一个终端:
telnet localhost 3547
哪个可以成功建立连接,但在几秒钟内,由于我之外的原因,服务器关闭了连接.阅读该文档handle_call/3,{noreply, NewState}
被允许为好.
有人可以解释一下吗?感觉超级混乱我.
源代码
-module(server). -mode(compile). -behavior(gen_server). -compile(export_all). -export([ main/1 , start/0 , stop/0 , stop_and_wait/0 ]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). -define(DEFAULT_PORT, 3547). -record(state, {port, lsock}). start_link(Port) -> gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). start() -> start_link(?DEFAULT_PORT). stop() -> gen_server:cast(?SERVER, stop). stop_and_wait() -> gen_server:call(?SERVER, stop, infinity). init([Port]) -> {ok, LSock} = gen_tcp:listen(Port, [{active, false}, {reuseaddr, true}]), {ok, #state{port = Port, lsock = LSock}, 0}. handle_call({do_stuff, Arg}, _From, State) -> io:format("do_stuff is called with ~p~n", [Arg]), % {reply, ok, State}; {noreply, State}; handle_call(stop, _From, State) -> {stop, normal, ok, State}. handle_cast(stop, State) -> {stop, normal, State}. handle_info(timeout, #state{lsock = LSock} = State) -> Server = self(), Listener = spawn(fun() -> listen(Server, LSock) end), {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_Oldvsn, State, _Extra) -> {ok, State}. listen(Server, LSock) -> {ok, Socket} = gen_tcp:accept(LSock), gen_server:call(?SERVER, {do_stuff, 1}), listen(Server, LSock). main(_) -> io:format("~p~n", [ok]), ok.
Steve Vinosk.. 9
允许{noreply, NewState}
从gen_server:handle_call/3
实现返回,但这并不意味着gen_server
不必回复该调用.相反,在这种情况下,假设gen_server
将在稍后使用该gen_server:reply/2
呼叫回复.
默认超时为gen_server:call/2,3
5秒.您的代码中发生的事情是您的listen/2
函数在接受套接字的进程中运行,因此是该套接字的所有者,然后调用它gen_server:call(?SERVER, {do_stuff, 1})
.由于您gen_server
没有回复该呼叫,因此gen_server:call
5秒后超时,终止进程并因此关闭套接字.
允许{noreply, NewState}
从gen_server:handle_call/3
实现返回,但这并不意味着gen_server
不必回复该调用.相反,在这种情况下,假设gen_server
将在稍后使用该gen_server:reply/2
呼叫回复.
默认超时为gen_server:call/2,3
5秒.您的代码中发生的事情是您的listen/2
函数在接受套接字的进程中运行,因此是该套接字的所有者,然后调用它gen_server:call(?SERVER, {do_stuff, 1})
.由于您gen_server
没有回复该呼叫,因此gen_server:call
5秒后超时,终止进程并因此关闭套接字.