Sockets gen_tcp:接受错误侦听套接字是否已关闭?
为初学者编写一个非常简单的TCP服务器,但对我来说,gen_TCP:accept在我的'accept_loop'函数中一直在调用时立即返回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
{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}
。